Programmatically executing a 2.x View

TL;DR: don’t do it! Execute a display instead.

Drupal Views are a good half-way house between user-friendly elegance and writing the SQL yourself. With this in mind, you might want to use them as a robust database API in your own code: you don’t need to think about precisely what’s stored in which table, but execute the view instead.

Working out precisely what you have to do to run a view isn’t straight forward. This now elderly post on Earl “Views” Miles’ blog provides some clues, but only by using page-display rendering as an example. Ideally, we want to avoid running our view through the whole theme layer, as that’s just lost CPU cycles. So what do we do to run our own view?

It turns out to be 90% easy, but 10% ever so subtle. Here is the usual stab, based on Earl’s example:

<?php
$view = views_get_view('MY_VIEW_NAME');
$view->set_arguments(array($my_first_arg, $my_second_arg, ...));
$view->set_display("DISPLAY_NAME");
// This next line is wrong.
$view->execute();

However, that doesn’t quite work. The annoying thing is that it almost works; it just doesn’t quite work. For a start, the number of items per page remains at the default, 10. This is a clue that something else needs to be invoked. But what?

Following that clue, go to the view’s own edit page and click preview. You should see that this preview does indeed respect paging. So what gives? Try invoking debug_backtrace() in View’s set_items_per_page() method, and the devel dsm() function to dump out the contents into Drupal’s messages area.

When you click on “Preview” again to refresh it, you should find that the backtrace includes a call by $view->preview() on $view->pre_execute(), and this is what calls the method to set the paging.

The only other way to call the pre-execute function? $view->execute_display(‘DISPLAY_NAME’). It’s slightly confusing and leaves you with the worry that there might be a pre_execute_display() method that you’re also somehow omitting to call…. Also, DISPLAY_NAME ought to default to, well, “default”, but when we omitted it, paging limits were once again not respected.

Here’s the correct code:

<?php
$view = views_get_view('MY_VIEW_NAME');
$view->set_arguments(array($my_first_arg, $my_second_arg, ...));
$view->execute_display("DISPLAY_NAME");

Your results should be available in an array called $view->result. (note: not singular!) This should respect all paging/offset settings for your display, although of course if you actually want to retrieve page 3 of your results, you’re going to have to do a bit more programming!