The joy of views_embed_view()

I love Views. For those who don’t know it; it’s basically a visual query builder that you want to use in every Drupal project. You might use it to create listings of content, commens, users, and what not. Add arguments, filters, sorts, a search box… you name it. Views can do anything! Well, almost anything.

I use it on a daily base for years now and I keep inventing new stuff it can do. A few weeks ago I had to build an overview that got me stuck. The overview was a list of forums, and for each forum the latest 3 comments. So what I basically needed was a view within a view. First, a view that shows all forums. And then a view that shows the three latest comments for each forum. The first views is easy; just an overview of node type ‘Forum’ where status = ‘Published’ ordered by date. You know the drill.

The second one is a bit harder. Views has the ability to use Contextual Filters (previously known as arguments) that can be used as dynamic filters. An example is a list of related items in the sidebar, where you need the Node ID given in the URL to find related content. For my overview, I’ve added the contextual filter Comment: Nid (The node ID to which the comment is a reply to).

I tried to combine the two views via the interface but didn’t manage. Gladly I discovered the function views_embed_view() which can be used to retrieve the output of a view from within your custom module. The function has three arguments:

  1. The system name of the view (forum_comments)
  2. The display name of the view (block_1 for example)
  3. And the last argument can be used to pass arguments

So I wrote a custom block (using hook_block_info() and hook_block_view() that did something like this:

$result = db_query("SELECT n.nid FROM {node} n WHERE n.type = 'forum' AND n.status = 1 ORDER BY n.sticky DESC, n.created DESC");
$forum_nids = array_values($result->fetchCol());
foreach ($forum_nids as $nid) {
  print views_embed_view('forum_comments', 'block_1', $nid);
}

Ain't that cool? If you want to use views_embed_view() with several arguments at once, that’s also possible. Keep in mind that you cannot use an array to pass the arguments, you need to seperate those argument with plus-characters or comma's. Example:

views_embed_view('forum_comments', 'block_1', implode('+', $nids));

The best part is that you can still use the Views interface to sort. order and change the way the comments are displayed. 

Next post

Exporting your module configuration using Ctools or with custom code - when to use which method?

Read More »

Comments

views_embed_view

I recently had to prepare a navigation block that presented X latest project nodes, which normally would be a piece of cake even for a Views novice. The catch was however that I had to group them by taxonomy term in a way that is not supported by Views UI. The views_embed_view came to the rescue - I prepared 2 sub-views and printed them out in my custom hook_block_view. I tried also another way - by building the markup with EntityFieldQuery which was surprisingly easy to do.

I still wish there was a "barebone" display style in Views that generates minimized markup with no wrappers whatsoever, except where necessary (such as li/ol or a when asked to list or hyperlink an item). Having to overwrite the markup in several places is a pain. This might be a challenge for myself to write such a useful module.

And exposed forms?

Thank you very much for your overview.

I run into another problem: I have two views for the same content type: one with only the first result of my query with a bigger image and some more informations as teaser and the other view with the next 10 Elements of the query and a pager etc.

For this view I also got an exposed form - but the exposed form filters only apply to the second view.

Is there any possibility to add the exposed form filters to the views_embed_view command?

Use Display Suite

Display Suite has a views integration in which you can use alternating view modes. With this, you can set the first item to use a different view mode than the other items.