How to Export Your Views to Code And Why

Here's a quick tip for managing Views that I've used for years. The concept has seen many iterations at the various shops I've worked for. At this point it's a bit of folklore, no one knows where this specific idea originated from, but it doesn't really matter either. Feel free to yell at me, shake a fist and say "It was merlinofchaos!" It probably was. Anyway, it's been passed down through the ages, through some of my great past and present co-workers and I now I bestow it onto you.

But first, the "why". You might think that exporting Views to code is reserved for module developers who contribute to Drupal.org and need to package a View with their module, and has no real value for the average dev. Not so. Exporting Views to code has enormous workflow benefits in a Dev-Stage-Prod workflow and for collaborating with other devs. When all your Views are exported to code you get the immediate benefit of removing the database from the mix and you add the ability to put your Views under version control. Once your Views are under version control you can now easily push the changes between environments, and what would have taken some inordinate amount of manual steps to deploy on production is minimized to simply pushing code and flushing Views' cache.

What About Features?

I hear you, all you Features lovers. Don't think I'm ignoring you. You might be thinking "Why do this by hand when anybody who's anybody knows that Features does this for you?!" Don't get me wrong, Features does have its place and in certain situations its a great alternative to the DIY method I'm about to present. Our rationale for DIY vs. Features in this case is simply that Features adds well... features we don't need, additional complexity, and overhead, and if we can't justify the overhead of a module, we don't use it. For just this simple task, its too much. We generally like to use this this method to maintain all Views on a site, across all custom modules, in one place.

The Code

There are two hooks involved and a simple file structure to follow. This particular iteration of this concept comes from our very own CTO.

First we need to register our intent with the Views module.

/**
 * Implements hook_views_api(). 
 */ 
function MY_MODULE_views_api() { 
  return array(
           'api' => '3.0', 
           'path' => drupal_get_path('module', 'MY_MODULE') . '/views' 
  ); 
}

Next we need to do the heavy lifting and expose our exported Views. Don't forget to clear the caches to register these hooks when you're done writing them.

/**
 * Implements hook_views_default_views().
 *
 * Imports views from the /views directory.
 */
function MY_MODULE_views_default_views() {
  $path = __DIR__ . '/views/*.view.inc';
  $views = array();
  foreach (glob($path) as $views_filename) {
    $view = FALSE;
    require_once($views_filename);
    $views[$view->name] = $view; // $view exists in the included file.
    unset($view);
  }
  return $views;
}

The above assumes that you have at least one file with an exported View in it called SOMENAME.view.inc and that its located in your custom module at MODULEFOLDER/views/SOMENAME.view.inc

I should mention too that I particularly like this iteration of hook_views_default_views() because it automatically adds each View to the $views array. In older iterations you'd have to manually add a snippet to the bottom of each of your View exports to accomplish the same thing. It's a simple change but it makes a big difference.

Exporting

That's it for the custom code. Now the only thing you need to do is start exporting Views, one per file, into files like: SOMENAME.view.inc. Just be sure to add an opening php tag at the beginning of each export. You can find links to export your View on the Views listing page or in the UI for the View you're editing.

Putting It All Together

The last steps after exporting your View is to flush Views' cache at /admin/structure/views/settings/advanced and finally to revert your View in the UI. This last step seems a bit counter-intuitive but think of it this way. You created a View in the database to start with, then you exported the View to code, but the site is still running the database version. By reverting you're telling Views to use your code version instead.

As you go along building out your site or maintaining it, you can still make changes to Views in the UI. When you do, you'll see in the interface that the View is being run from the database. Repeat the export and cache clear steps as needed to start running your Views from code again. When deploying Views changes to production, you'll just push up your code changes that include your Views modifications, flush your Views cache and boom, your Views changes are now live!