Using preprocess hook on specific node type in Dru

2019-07-02 08:22发布

问题:

I've had success using preprocess page hooks such as:

function mytheme_preprocess_page__node_front(&$variables) {
    ...
}

and

function mytheme_preprocess_page__node_12(&$variables) {
    ...
}

which correlate with custom templates named page--front.html.twig and page--12.html.twig, respectively.

I'm trying to implement the same hook and template pairing for a content type called Video. I understand that there is a difference in that my examples have been custom templates for specific pages while my goal is a custom template for an entire content type, but I got a custom template called node--video.html.twig that works as a template for all video pages. However when I try to write a hook based on this template name:

function mytheme_preprocess_node__video(&$variables) {
    ...
}

this does not work. I think that I either can't define a hook like this, or I'm just naming it incorrectly. I found a couple threads somewhat relating to this such as this that seem to imply that I need to define a hook for all nodes and then write an if statement that handles each type separately. So.......

Final Question: Can I define a hook for an entire content type, and if so what am I doing wrong?

回答1:

Use condition within the preprocessor to get the node type and then either do your logic within, or invoke another function.

function mytheme_preprocess_node(&$variables) {
  switch ($variables['node']->getType()) {
    case "video":
      // ...
    break;
    case "something_else":
      // ...
    break;
  }
}

You could in theory emulate what you are trying to achieve by trying to invoke a function named mytheme_preprocess_node__" . $variables['node']->getType() if it exists, but is too much fuss without a clear benefit.



回答2:

In drupal 7 from zen template I used to use this generic solution. I think it is still a viable solution on drupal 8:

function mytheme_preprocess_node(&$variables) {
  ...
  // Add global modification that works for all node type
  $function = __FUNCTION__ . '__' . $variables['node']->getType();
  // Each node type can have its own specific function
  if (function_exists($function)) {
    $function($variables, $hook);
  } 
  ...
}

You can then now add preprocess function that will only works for you node type.

function mytheme_preprocess_node__video(&$variables) {
    ...
}

Instead of having one big function, each node type's preprocess logic has its own function. It's better for maintainability.