Project:Views
Version:6.x-2.8
Component:Miscellaneous
Category:support request
Priority:normal
Assigned:Unassigned
Status:closed (fixed)

Issue Summary

Another question, sorry.

Since there are templates for each view, does that mean there are dynamically generated preprocessors somewhere? I think not, since I can't find any code which looks like it might be doing that. To illustrate my example:

* view named my_first_view
* template is views-view--my-first-view.tpl.php

Following that logic through, one would expect to find (dynamically generated, of course):

<?php
function template_preprocessor_views_view__my_first_view() {
  ...
}
?>

Which, following on again, would imply I can extend that with this in my own module:

<?php
function my_module_preprocessor_views_view__my_first_view(&$variables) {
 
$variables['new_var'] = 'foo';
}
?>

Comments

#1

Status:active» fixed

There aren't dynamically generated preprocess functions; instead, all of the theme functions use the base preprocessor automatically. So views-view--my-first-view.tpl.php still uses template_preprocess_views_view(&$vars) as its preprocessor function.

You can add preprocess functions for specific views with the exact same naming conventions. Note that that it's named *_preprocess_ not preprocessor_.

Note that currently Drupal's design requires that you have the .tpl.php file in order to have the preprocess function (though you could drop in a generic preprocess function and do switches based upon information contained within the $vars['view'] variable. There's an issue for this which is fairly easily found by going to the Drupal queue and searching in the 'theme system' queue.

#2

You can add preprocess functions for specific views with the exact same naming conventions. Note that that it's named *_preprocess_ not preprocessor_.

Sorry to be slow, but I don't want to spend hours scratching my head because I misunderstood you... So you mean I can do this in my module?

<?php
function template_preprocess_views_view__my_view(&$variables) {
 
$variables['my_var'] = 'foo';
}
?>

There's an issue for this which is fairly easily found by going to the Drupal queue and searching in the 'theme system' queue.

I've just been staring at the issue queue for half an hour and I don't see it. =(
It's late, I need my dinner, I'm going home. To be continued tomorrow.

Thanks again for your time!

#3

You would use your theme name in place of template and as long as you have views-view--my-view.tpl.php yes.

Note that if using linux, another trick you can use is symbolic links so that you can have the same template without copying it, if you only want to change stuff in the preprocess function. =)

#4

Note that if using linux, another trick you can use is symbolic links so that you can have the same template without copying it, if you only want to change stuff in the preprocess function. =)

Ooooo, nice idea! =)

Or junction in Windows. But I've had horrible issues with that in the past. Anyway, the dev and stage servers are Fedora and production server is Redhat, so we're good there.

Thanks *again*!

#5

interesting issue-- just as an fyi the issue merlin is referring is i believe: Themes cannot have a preprocess function without a corresponding .tpl.php file

#6

Thanks WorldFallz. =)

Merlin, FYI, I've blogged a summary of my day researching here:
http://www.drupaler.co.uk/blog/theming-views-drupal-6x/67

If you find five minutes to read it and I've got anything wildly wrong, let me know.

I'm also wondering if this is possible on a module level. My experimentation indicates not, but I find this odd. If themename_preprocess_views_view__my_view works, I would expect modulename_preprocess_views_view__my_view to work too, but it seems this is not the case?

#7

It can be made to work but only if you use hook_theme() to register a .tpl.php file, which can then be overridden later in the the theme itself. The reason this is necessary is that discovery of the template happens during the theme section, which happens after modules; so the module's preprocess hook isn't looked for because that variant of the theme function does not (yet) exist.

#8

Ahhh, gotcha. Thanks! =)

I'd prefer this in a module because then if I switch theme my custom vars will still be available.

#9

subscribing

#10

Greg;

There is one quibble with your article I have:

The Views module is an excellent example of this. There is a preprocess function called template_preprocess_views_view() which is responsible to generating *all* view tpl files. Here are examples of valid view template file names:

Not all view tpl files; only variants of the views_view theme. For example, this won't handle views-view-list.tpl.php. But the basic point is correct: phptemplate_preprocess_views_view_list() will handle all *variants* of views-view-list.tpl.php such as views-view-list--myview--displayid.tpl.php

Also, one mention is that you can pretty safely override views-view-field.tpl.php (an individual field) not as a template. Earlier I mentioned that Views wants everything to be a template but this is one place that I actually fibbed slightly, due to misremembering.

Fields are actually handled by theme function for performance reasons:

<?php
/**
* Display a single views field.
*
* Interesting bits of info:
* $field->field_alias says what the raw value in $row will be. Reach it like
* this: @code { $row->{$field->field_alias} @endcode
*/
function theme_views_view_field($view, $field, $row) {
  return
$field->render($row);
}
?>

However, to make it work automatically when you implement a field template, I include a preprocess function that isn't used unless a template is discovered:

<?php
/**
* 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.
*/
function template_preprocess_views_view_field(&$vars) {
 
$vars['output'] = $vars['field']->render($vars['row']);
}
?>

For performance reasons, not using a template for individual fields is actually a good idea. Sorry about the misinformation, and thank you for writing that so I realized my error.

(both functions, above, are in theme/theme.inc)

#11

Thanks for reading and I will update it now. =)

I won't bother documenting the additional point about theming fields, as I link to this issue anyway from that article.

#12

Changed to read:

The Views module is an excellent example of this. There are several preprocess functions within the Views module which are generic but have specific purposes. One is called template_preprocess_views_view() and it is responsible for generating *all* view tpl files with filename in the form views-view--my-view-name.tpl.php. Another, template_preprocess_views_view_list(), acts upon all variations of views-view-list--my-view-name.tpl.php, etc. You get the idea.

All possible variations of valid view template file names are demonstrated here, each set of variations having its own default preprocess function provided by the Views module:
http://views.doc.logrus.com/group__views__templates.html

#13

Hi Merlin;
following on from your suggestion:

It can be made to work but only if you use hook_theme() to register a .tpl.php file, which can then be overridden later in the the theme itself. The reason this is necessary is that discovery of the template happens during the theme section, which happens after modules; so the module's preprocess hook isn't looked for because that variant of the theme function does not (yet) exist.

i tried setting up the following in my module:

preprocessor function :

<?php

function modulename_preprocess_views_view_fields__viewname(&$variables) {

}
?>

theme function:

function modulename_theme() {
  return array(
    'views_view_fields__VIEWNAME' => array(
    'arguments' => array('view' => NULL, 'fields' => NULL, 'row' => NULL),
    'template' => 'views-view-fields--VIEWNAME',
    ),
}

I also have a tpl file in my theme directory - views-view-fields-VIEWNAME.tpl.php

I tried passing up additional variables from the preprocessor to the template file but it doesnt seem to invoke the preprocessor function at all :(

#14

Status:fixed» closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

#15

Status:closed (fixed)» postponed (maintainer needs more info)

Hi,

Setting this active again because of #13. I tried it too and couldn't get it to work. And I can't find a comprehensive guide to this. I would've expected the code in #13 to work, and I did create a hook_theme() too, but nothing. Any pointers? =(

#16

To follow on, printing out the $info array in the theme() function confirms the module preprocess is failing to register:

Array
(
    [template] => views-view-table--insights-authors
    [path] => sites/defaqto.com/themes/defaqto/templates/views
    [arguments] => Array
        (
            [view] =>
            [options] =>
            [rows] =>
            [title] =>
        )

    [original hook] => views_view_table
    [type] => theme_engine
    [theme path] => sites/defaqto.com/themes/defaqto
    [theme paths] => Array
        (
            [0] => sites/defaqto.com/themes/defaqto/templates/views
        )

    [preprocess functions] => Array
        (
            [0] => template_preprocess
            [1] => template_preprocess_views_view_table
            [2] => mytheme_preprocess_views_view_table__insights_authors
        )

)

For this to work I think preprocess functions needs to look like this:

    [preprocess functions] => Array
        (
            [0] => template_preprocess
            [1] => template_preprocess_views_view_table
            [2] => template_preprocess_views_view_table__insights_authors
            [3] => mytheme_preprocess_views_view_table__insights_authors
        )

This is the code, which should work according to other module examples and the docs, but doesn't:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
    ),
  );
}

function
template_preprocess_views_view_table__insights_authors(&$variables) {
 
$variables['foo'] = bar;
}
?>

Even tried this, to try and force our preprocess to stick, and it didn't do anything either:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'preprocess functions' => 'template_preprocess_views_view_table__insights_authors',
     
'override preprocess functions' => true,
    ),
  );
}
?>

#17

Status:postponed (maintainer needs more info)» active

What if you add an 'original hook' directive in there? I'm not sure that actually works though.

#18

Will try on Monday and report back. =)

#19

Mixed results on this. With the following code:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'original hook' => 'views-view-table--insights-authors',
    ),
  );
}
?>

I get the following $info output from theme():

    [preprocess functions] => Array
        (
            [0] => template_preprocess
            [1] => mymodule_preprocess_views_view_table__insights_authors
        )

As you can see, the Views module's default table preprocess gets dropped. So this seems to work, if I do this in my preprocess:

<?php
function mymodule_preprocess_views_view_table__insights_authors(&$vars) {
 
// invoke the missing Views preprocess before we mess with the vars
 
template_preprocess_views_view_table($vars);
 
$vars['foo'] = 'bar';
?>

Interestingly, if I do this:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'original hook' => 'views-view-table--insights-authors',
     
'preprocess functions' => 'template_preprocess_views_view_table',
    ),
  );
}
?>

Then $info in theme() looks like this:

    [preprocess functions] => Array
        (
            [0] => template_preprocess
            [1] => template_preprocess_views_view_table
            [2] => mymodule_preprocess_views_view_table__insights_authors
        )

Which is almost correct, except the structure of the rows output changes (it's an object instead of an array and the data is raw instead passed through the correct handlers) so I guess this approach misses something somewhere.

Finally, I tried this, since I now know what the structure should be - I hard-wired it in my module:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'original hook' => 'views-view-table--insights-authors',
     
'preprocess functions' => array(
       
0 => 'template_preprocess',
       
1 => 'template_preprocess_views_view_table',
       
2 => 'mymodule_preprocess_views_view_table__insights_authors',
      ),
    ),
  );
}
?>

This approach works fine. I'm not sure why this third approach would result in properly themed fields and the second one would not, but the first and third approaches both seem to work, while the second one works to an extent but for some reason the view output is not "finished".

#20

Ok, I understand the problem and what's wrong.

This code works:

<?php
function ptest_theme($existing) {
  return array(
   
'views_view__ptest_tracker' => array (
     
'arguments' => array('view' => NULL),
     
'template' => 'views-view--ptest-tracker',
     
'original hook' => 'views_view',
    ),
  );
}
?>

HOWEVER, there is a caveat. It ONLY works if the module weight > views; because it needs the pre-existing views theme function to exist for the 'original hook' directive to work.

In place of it, you can add the preprocess function manually, like Greg did above.

#21

Theme developer module helps a ton for understanding what .tpl.php file names you can use to customize your output. It also helps you know the variables that get passed into those templates. But knowing the available preprocess functions could be useful. I made a patch for theme developer at #312061: Show which preprocess functions were called on a theme call. Feedback welcome.

#22

Fiddled around with this some more this morning. I find the easiest way to make this work is to have NO 'original hook' at all (the red herring in this was I accidentally used hyphens instead of underscores in my 'original hook', so it wasn't doing anything anyway). This definitively works for me:

hook_theme()

<?php
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
    ),
?>

preprocess function

<?php
function mymodule_preprocess_views_view_table__insights_authors(&$vars) {
 
// invoke the missing Views preprocess before we mess with the vars
 
template_preprocess_views_view_table($vars);
 
$vars['foo'] = 'bar';
?>

Whereas trying to use the 'original hook' takes me back to the problem I had with the second approach in #19, the data is unfinished and unthemed.

Also, we tried to mirror this approach with mymodule_preprocess_views_view_fields__view_name() and could not get it to work at all, in any combination. Weird! =(

#23

Greg: Read #20. I promise you, it works 100% *if* you set the module weight > views.

#24

Ok, will try this properly. I confess I didn't try your module weight tip, because I probably misunderstood this and tried to do the same again:

In place of it, you can add the preprocess function manually, like Greg did above.

It seems this does not work in all cases.

#25

BTW, I plan to take what this issue is generating and write up a documentation page about it (and putting Views in a module in general) either today or tomorrow. I probably was being too lazy when I said 'above' since you tried a lot of things. The one I was pointing at that seems like it should work reliably if you are unable/unwilling to change the module's weight:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'preprocess functions' => array(
       
'template_preprocess',
       
'template_preprocess_views_view_table',
       
'mymodule_preprocess_views_view_table__insights_authors',
      ),
    ),
  );
}
?>

Note that I removed the erroneous 'original hook' designation. Also I should add that 'arguments' is wrong there too, and that could have unintended consequences (like, theme() shouldn't be able to figure out how to translate the arguments to variables without that).

#26

Sounds great - look forward to reading the page! =)

#27

Status:active» fixed

This is now documented in the advanced help.

--project followup subject--

Automatically closed -- issue fixed for two weeks with no activity.

#28

Status:fixed» closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

#29

Might be me, but I do not see this in the Advanced help for Views. Looking in HEAD.

#30

#31

Status:closed (fixed)» postponed (maintainer needs more info)

I'm still having some problems with this - figured I'd post here so the thread continues, rather than starting a new one, but let me know if that's a bad idea...!

Following the docs, my module's weight > than Views' weight, check!

hook_theme() looks like this:

<?php
/**
* Implementation of hook_theme().
*/
function cck_gallery_theme() {
  return array(
   
'views_view_unformatted__gallery_contents' => array (
     
'arguments' => array('view' => NULL, 'options' => NULL, 'rows' => NULL, 'title' => NULL),
     
'template' => 'views-view-unformatted--gallery-contents',
     
'original hook' => 'views_view',
    ),
  );
}
?>

Template is in the root of the module (which seems to be where it's wanted - Drupal complains if it isn't there) and is named 'views-view-unformatted--gallery-contents.tpl.php'

Preprocess simply looks like this:

<?php
function cck_gallery_preprocess_views_view_unformatted__gallery_contents(&$vars) {
 
print_r($vars);
}
?>

Nada! Firefox says "No document" or "No data" or somesuch.

But if I ditch the 'original hook' part everything is fine! WTF?! =(

I mean, it's cool because it works, but clearly I would rather understand why 'original hook' in hook_theme() seems to cause Drupal 6.9 to crash...

#32

I'm using Organic Groups and I want to customize the default og_ghp_ron view that comes with it. By default the view uses the "unformatted" view style. I changed the style to a table style and all the data I need is in there correctly.

However, essentially what I want to do is pluck out the fields and arrange them however I want in a table. In order to do that properly, I thought I should use a preprocessing function to redefine the field names, so that I could just drop them into a template wherever I want. Some of the fields are CCK fields.

I created a module and defined the preprocessing function there but when I did that the table view got messed up and for example, the dates lost their format and were not expressed the way they should.

I'm not a PHP whiz, so I'm finding it hard to find some concrete examples on what the correct development path to correctly achieve this basic task is.

Should I be creating a preprocess function per view (preferred), or just change the default views preprocess functions (field, unformatted, table, grid, etc.)? If I do, then how do I correctly redefine variable names and format the date (which is getting messed up) through the preprocessing function? How about changing the date format then through a .tpl.php file?

Which style should I be using (table, list, unformatted, grid) to extract the fields and why use one style and not the other?

What's the difference between the two row styles (fields, nodes)?

Some of the template files for example use code in them (such as content-field.tpl.php)? Should they be moved to the preprocess function instead to separate presentation from logic?

Are there any complete examples of calling embedded views from within a .tp.php template file, and how do you call one view from another view? Wouldn't it be easier to write a view like this and customize it in code rather than through an interface?

Unfortunately there aren't any beginning to end examples or best practices to perform common views tasks such as this out there, because I'm sure a lot of people have run into it this issue.

Thanks for any help,
Mo
www.itwrite.com | Having fun with Drupal

#33

Hi guys,

I'm having troubles with adding a preprocess function for a specific display.

So, I have a view, with a particular display.
In my module I have this code :

<?php
function modulename_theme($existing, $type, $theme, $path) {
  return array(
   
'views_view__rfi_taxonomy_term_emission__block_3' => array(
     
'arguments' => $existing['views_view_unformatted']['arguments'],
     
'template' => $existing['views_view_unformatted']['template'],
     
'path' => drupal_get_path('module', 'modulename') . '/theme',
     
'original hook' => 'views_view_unformatted',
    ),
  );
}
?>

Then I wrote this function :

<?php
function rfi_emission_edition_preprocess_views_view__rfi_taxonomy_term_emission__block_3(&$variables) {
 
//...
}
?>

Unfortunately, my function gets a NULL $rows, so does my template...
Any idea ?
Thanks

#34

Version:6.x-2.0-rc1» 6.x-2.8

I am trying to make a module to implement a new style and the preprocess function is in the theme registry but it is not executed. I changed the weight of the module but it still does nothing. I see this thread is quite old, but I cannot find any resource doc to clearify why is this happening.

I followed the steps here http://groups.drupal.org/node/10129 and http://views-help.doc.logrus.com/help/views/api-default-views but it still does not work.

#35

I have just got this working locally. I thought I would post my process here as it is not quite straigtforward.

First make sure your modules weight is > views

Secondly copy the template you would like to add a preprocessor to to your modules directory. Rename it to be something in the list of templates in theming information.

Edit hook theme like this (but change to use the existing view that you need to override.

<?php
function mymodule_theme($existing, $type, $theme, $path) {
 
// Copy the exsisting views theme from the existing array.
 
$override = $existing['views_view_row_rss'];
 
// Add my preprocessor to the list of preprocess functions
 
$override['preprocess functions'][] = 'mymodule_myfunction';
 
// Point to a template so that this view will be used.
 
$override['template'] = 'my_more_specific_template_name';
 
$override['path'] = drupal_get_path('module', 'path');
 
//If you don't unset this you get some theme errors.
 
unset($override['file']); 
 
// Return your theme handler.
 
return array('my_more_specific_template_name' => $override);
}
?>

You should then be able to write your preprocess code in the function mymodule_myfunction.

I had issues before this with the args array being wrong, using the above method your args should keep up with any changes in the views args.

#36

Hi everyone,
About the mymodule_preprocess caveat that merlin mentions in #20 regarding module weight: why can't one just add the preprocess function in a hook_theme_registry_alter?
Something like this:

  function mymodule_theme_registry_alter(&$theme_registry) {
    //dpm($theme_registry);
    $theme_registry['views_view__YOUR_VIEW_NAME_HERE']['preprocess functions'][] = 'mymodule_preprocess_func';
  }

  // now go on and play with your new preprocess function
  function mymodule_preprocess_func(&$vars) {
    // etc
  }

It seems to work pretty nice.
Any thoughts?

#37

Status:postponed (maintainer needs more info)» needs review

#38

Status:needs review» active

Needs review is only to review patches.

#39

Status:active» closed (fixed)

I guess we ought to close this and direct people to the Drupal 6 theming system. From my experience this all works ok now. It was only a support request when we raised it and any discussion/suggestions about approaches to using templates and preprocess functions ought to occur in the appropriate handbooks:
http://drupal.org/node/223430
http://drupal.org/node/352970

Btw, on my travels I found this, which might be useful - I don't know if it's still an issue:
http://drupal.org/project/preprocess_order_corrector

#40

#36 worked perfectly for me and is a heck of a lot simpler than the other options fwiw.

#41

I have a situation with hundreds of view tpl's and corresponding preprocess functions. I inherited this, and I'm working to tame this wild ecosystem. In the meantime, it has been suggested to me that I should maintain the views in a module. Do I need to register each preprocess in the module? I've tested one view according to the advanced help, it works, as far as the view residing in the module, I've updated the weight to 11, but I can't get the preprocess functions to be read.

Thank you.

#42

Is there any reason why this is a bad idea? It works.

function mymodule_theme_registry_alter(&$theme_registry) {
foreach ($theme_registry as $idx=>$value) {
if(strstr($idx, 'views_view_')) {
$function = 'mymodule_preprocess_'. $idx;
if(function_exists($function)) {
$theme_registry[$idx]['preprocess functions'][] = $function;
}
}
}
}

#43

#44

Yes! #36 works like a charm!

#45

For whoever is interested I created a module to fix this issue so that you don't have to do the

<?php
hook_theme_registry_alter
?>
manually for each of your views: views_preprocessors. The dev snapshot for D6 should appear on the project page within the next 12 hours and I should have the 7.x version up by then too. If you are impatient do a git checkout.

Cheers,
Andrei

#46

#36 works for me.

#47

#36 causes D7 view page to whitescreen

#48

#25 works fine for me. And the only problem I have is that, I need to keep :

views-view-table--insights-authors.tpl.php

in my current theme folder, in order to make it work properly.

Any ideas how to support the template file in my custom module's folder?

Thanks.

#49

What I did:

<?php
/**
* Implementation of hook_theme().
*/
function mymodule_theme() {
  return array(
   
'views_view_table__insights_authors' => array (
     
'arguments' => array(),
     
'template' => 'views-view-table--insights-authors',
     
'path' => drupal_get_path('module', 'mymodule'),
     
'preprocess functions' => array(
       
'template_preprocess',
       
'template_preprocess_views_view_table',
       
'mymodule_preprocess_views_view_table__insights_authors',
      ),
    ),
  );
}
?>

However, seems to me that the 'path' does not work, if I remove the template in my theme folder, and only keep it in my module's folder, then I will have following error:

PHP Fatal error: Call to a member function sanitize_columns() on a non-object in ../sites/all/modules/contributed/views/theme/theme.inc on line 323

Any pointers?

Thanks.