August 7, 2009

It is a good Drupal development best practice to embed each of your views in code instead of storing them in the database. This technique will allow your views code to be managed by your version control system which makes pushing up changes to views from development to staging to live a much cleaner process. Additionally, since the views code is being loaded from disk instead of the the more expensive database you will see a modest performance improvement. All in all a pretty good thing.

However, getting this to work in practice can be a little tricky. The embedded views are *sizable* data objects and the standard implementation of the Views 2 hook to do this (hook_views_default_views()) leads to the creation of a *giant* function where each of your views is copied and pasted into your module file. Making changes to individual views later can be a real hassle.

To help solve this issue I took a cue from views implementation of organic groups and adapted a technique to allow each view to be stored in its own separate include file which is automatically detected by the module. The win here is to allow easy updating of each view (just delete its file and copy the new export over it) and not have to worry about a lot of other cruft. To make this happen, four steps:

First, you need to specify the define important hook_views_api in your module like so. This will tell Views 2 you are looking to do even bigger and better things.

/** * Implementation of hook_views_api(). **/ function my_great_module_views_api() {   return array(     'api' => 2,   ); }

Second, you need to create a file in your module directory that will include your hook_views_default_views() function. Including this as a separate file (instead of in the main module) will let Drupal decide when to pull in this hook and its pile of related views code.




Third, you need to define the actual hook in the file. The code below will define that hook and will setup logic to recursively look through a "views" subdirectory for views to include as defaults. The logic below will load any file in the "views" directory and expects the files to individually contain a $view object.

/** * Implementation of hook_views_default_views(). **/ function my_great_module_views_default_views() {   $files = file_scan_directory(drupal_get_path('module', 'my_great_module'). '/views', '.view');   foreach ($files as $filepath => $file) {     require $filepath;     if (isset($view)) {       $views[$view->name] = $view;     }   }   return $views; }

And finally, forth, you need to create the important "views" sub-directory and make the many different files inside that each include a single $view object. As a development practice I name each file with the same name as the view and use the .view file extension (example: my_view.view). It is a pretty easy process to export each $view from the views interface and include in the code.