6

I need to add a header to the page markup if a call to views_embed_view() retrieved any content, and hide it if not. Unfortunately, an empty view produces this markup:

<div class="view view-related-content view-id-related_content view-display-id-block view-dom-id-a62e1bda4cd2427adcbfba7ad95dec6e">









</div>

(I've left the spacing in to be as accurate as possible).

The view is set to hide results when the argument for the (only) contextual filter is not present.

How can I determine whether the view actually has any results, without incurring any extra DB overhead?

I'm looking to do this just with API functions as overriding templates for something so trivial is not palatable. I'm also not looking for any hacks (e.g. measuring the length of the return string and hiding the header based on that).

5 Answers 5

7

views_embed_view() does something along the lines of this:

function views_embed_view($name, $display_id = 'default') {
  $args = func_get_args();
  array_shift($args); // remove $name
  if (count($args)) {
    array_shift($args); // remove $display_id
  }

  $view = views_get_view($name);
  if (!$view || !$view->access($display_id)) {
    return;
  }

  return $view->preview($display_id, $args);
}

and views_get_view_result() does something along the lines of this:

function views_get_view_result($name, $display_id = NULL) {
  $args = func_get_args();
  array_shift($args); // remove $name
  if (count($args)) {
    array_shift($args); // remove $display_id
  }

  $view = views_get_view($name);
  if (is_object($view)) {
    if (is_array($args)) {
      $view->set_arguments($args);
    }
    if (is_string($display_id)) {
      $view->set_display($display_id);
    }
    else {
      $view->init_display();
    }
    $view->pre_execute();
    $view->execute();
    return $view->result;
  }
  else {
    return array();
  }
}

so you could combine them to make your own custom module embed like this:

function YOURMODULE_embed_view($name, $display_id = 'default') {
  $args = func_get_args();
  array_shift($args); // remove $name
  if (count($args)) {
    array_shift($args); // remove $display_id
  }

  $view = views_get_view($name);
  if (is_object($view)) {
    if (is_array($args)) {
      $view->set_arguments($args);
    }
    $view->set_display($display_id);
    $view->pre_execute();
    $view->execute();

    if (!empty($view->result[0])) {
      return $view->preview();
    } else {
      return FALSE;
    }
  }
  else {
    return FALSE;
  }
}

(D6 code above, D7 is quite similar)

2
  • just looking "inside" ->preview, it might call pre_execute() again, so maybe some more deeper api digging might be needed
    – Jimajamma
    Commented Dec 6, 2012 at 15:25
  • That worked straight up, doesn't seem to incur any extra db overhead so looks great. Thanks again
    – Clive
    Commented Dec 7, 2012 at 14:10
10

You could use views_get_view_result() which returns an empty array if the view has no result to display.

1
  • Cool thanks. Is there another function I can pass those results to to get the built view?
    – Clive
    Commented Dec 6, 2012 at 15:18
5

I had the exact same problem. This is what i did -

$view = views_get_view('view_name');
$print_view = $view->preview('display_id', array('argument1','argument2'));
if(!empty($view->result)) {
  print $print_view;
}

Hope that helps somebody.

2

With help from the posts by Jimajamma and bsfoo116, here's the straight up short answer:

$checkempty = views_get_view_result('my_view_name', 'my_display_name');
if (!empty($checkempty)) print views_embed_view('my_view_name', 'my_display_name');
1

A lighter weight solution is to simply search the output for the text 'views-rows'. If there are no results, this text generally wont be rendered (though of course it will vary based on your specific configurations).

I was able to successfully use this in one of my projects to make sure a block got hidden appropriately.

$block['content'] = views_embed_view('volumes', 'default', $group_id);

if(strpos($block['content'], 'views-row') === false){
    $block['content'] = false;
}

Obviously the other solutions listed here are more complete, but this is a quick and straightforward way to do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.