3

I would like to override a Views-generated block's "Content: Title" field's href path (linked to nodes with "Link this field to the original piece of content") to append a query string ($_GET['page']).

An example:

this is the generated link:

<a href="/my_drupal_subdir/hu/my_test_alias/blabla" class="views ...">Blabla</a>

I would like this one:

<a href="/my_drupal_subdir/hu/my_test_alias/blabla?page=0,0,2" class="views ...">Blabla</a>

I would like to override the path and append a query string before it gets rendered as an HTML-link (<a>).

How should I do this? I think Views uses views_handler_field_node::render_link() and views_handler_field::render_as_link() which calls function l() or sg. like that which should be overridden. Of course, overriding theme_link() for modifying ALL the links is not a good way.


Here's an export of the simplest possible block view for Articles with pager id 3; the titles are linked:
http://pastebin.com/tmq0kZwT
I want to override the title links of this list to append a query string (to remember the actual pager when clicking on a node).

3 Answers 3

6

Here is the solution:

Put the following code to your theme's template.php file, and substitute MYTHEME with your own theme's name (or you can even put it in your module's file, and substitute MYTHEME with your module's machine name):

<?php

/**
 * Implements template_preprocess_views_view_field()
 * @see http://api.drupal.org/api/views/theme!theme.inc/function/template_preprocess_views_view_field/7
 * Process a single field within a view.
 * This preprocess function isn't normally run, as a function is used by default, for performance. However, by creating a template, this preprocess should get picked up.
 */
// /* -- Comment out this line if you want to use this function
function MYTHEME_preprocess_views_view_field(&$vars) {
  // $vars['output'] = $vars['field']->advanced_render($vars['row']);

  // @see http://drupal.org/node/939462#comment-4476264
  if (isset($vars['view']->name)) {
    $function = 'MYTHEME_preprocess_views_view_field__' . $vars['view']->name . '__' . $vars['view']->current_display;

    if (function_exists($function)) {
      $function($vars);
      // we can return to only use the specific preprocess function (it matters if there are more codes below in this function)...
      return;
    }
  }
}
// */


/**
 * Implements template_views_view_field__VIEW_MACHINE_NAME__DISPLAY_MACHINE_NAME()
 * @see template_views_view_field()
 * @see MYTHEME_views_view_field()
 */
// /* -- Comment out this line if you want to use this function
function MYTHEME_preprocess_views_view_field__block_of_articles__block(&$vars) {
  // $vars['output'] = $vars['field']->advanced_render($vars['row']);

  if (isset($vars['row']->nid, $vars['row']->node_title)) {
    $path    = drupal_get_path_alias('node/' . $vars['row']->nid);
    $options = array();
    if (isset($_GET['page'])) {
      $options['query'] = array(
        'page' => $_GET['page']
      );
    }

    $vars['output'] = l($vars['row']->node_title, $path, $options);
  }
}
// */

Don't forget to clear your cache!
This should only be done in cases when it's really needed: for example when an Article listing block (like this really simple one which you can import: http://pastebin.com/tmq0kZwT) is also displayed next to the article nodes, and we want the current pager position to be "remembered".

1

Normally you should change it in the View configuration.

But there is a tricky alternative by using hook_views_post_render and PHP DOM as follow:

/**
 * Implements hook_views_post_render().
 */
function MYMODULE_views_post_render(&$view, &$output, &$cache) {
  if ($view->name == 'my_view') {
    $doc = new DOMDocument();
    $doc->loadHTML($output);
    // ... do some HTML modifications here ...
    $output = $doc->saveHTML();
  }
}
2
  • Thanks, but I think it would consume much more resources than the accepted answer, especially when the generated HTML structure is large. This way you postprocess the whole structure (not only the field you'd like to override), you have to build a DOM tree, search for the appropriate HTML element, change it, and generate the HTML output. It costs much more time, memory, CPU resources, etc...
    – Sk8erPeter
    Commented Feb 23, 2015 at 16:39
  • It's just another way of doing it, as sometimes having different kind of views (Search API, YQL Views) can be surprisingly difficult, especially if they're not using SQL queries or proper node objects.
    – kenorb
    Commented Feb 23, 2015 at 16:49
0

Try using http://api.drupal.org/api/views/views.api.php/function/hook_views_pre_render/7

Altering the content can be achieved by editing the items of $view->result

function YOURMODULE_views_pre_render(&$view) {
  if ($view->name == 'your_view_name') {
    foreach($view->result as $k => $result) {
      if ($some_condition) {
        // do something to the result row
      }
    }
  }
}
2
  • thanks jwal, but what can I do with it to change the href path like I mentioned it in my example? Let's take an example, my $view->result[0] is the following: stdClass::__set_state(array( 'node_title' => 'My test node', 'nid' => '46', 'node_language' => 'hu', 'node_created' => '1347887053', )) - what then? How do I change the href path? I don't see any aliases, nor any real paths here. This way, I can NOT append any query strings at all, which would be the main point of this question. :)
    – Sk8erPeter
    Commented Nov 30, 2012 at 1:33
  • please see my updated question under the horizontal line with an example export of a really simple block view of Articles (I put it up to pastebin)! For example, I want to override the href path of the titles linked in the list. Thx. Here it is: pastebin.com/tmq0kZwT.
    – Sk8erPeter
    Commented Nov 30, 2012 at 1:50

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.