J'ai quelques types de contenu que je dois prétraiter de différentes manières. Donc template.php
dans mon thème foo
ressemble actuellement à:
function foo_preprocess_node(&$variables) {
if ('news' ==$variables['type']) _preprocess_news($variables);
if ('event'==$variables['type']) _preprocess_event($variables);
if ('alert'==$variables['type']) _preprocess_alert($variables);
...
}
function _preprocess_news(&$variables) {
...
}
function _preprocess_event(&$variables) {
...
}
function _preprocess_alert(&$variables) {
...
}
Je voudrais pouvoir spécifier une fonction de pré-traitement spécifique Drupal qui accrocherait le nom de la machine du type de contenu. J'ai essayé d'utiliser foo_preprocess_news
mais il n'est jamais appelé.
Y a-t-il une meilleure façon?
Le nom de la fonction de prétraitement est basé sur le nom du thème, donc pour theme_table()
votre fonction de prétraitement est MYTHEME_preprocess_table()
.
Comme il n'y a pas de fonction theme_node_node_type
, Un hook de prétraitement tel que foo_preprocess_news
Ou foo_preprocess_node_news
Ne fonctionnera pas hors de la boîte.
Vous pourriez remplacer le registre de thèmes afin qu'il se comporte différemment pour les nœuds, mais je ne le recommanderais vraiment pas; cela pourrait devenir très compliqué.
Je suis un grand fan de refactoring de code mais dans votre cas, je ne pense pas que ce soit nécessaire; si vous avez une logique complexe qui doit être exécutée dans votre hook de pré-traitement en fonction du type de nœud, alors le transformer en différentes fonctions de la manière que vous faites actuellement me semble une bonne pratique.
L'autre méthode, bien sûr, serait d'implémenter un module personnalisé pour chacun des différents types de contenu et d'implémenter hook_preprocess_node()
dans chacun. De cette façon, la fonction de prétraitement de chaque module peut être responsable d'un type de contenu différent.
Cependant, cela peut être exagéré pour votre situation; si vous n'avez pas de logique supplémentaire (c'est-à-dire une logique de prétraitement sans thème) à effectuer sur chaque type de contenu, cette méthode n'ajoute probablement aucune valeur supplémentaire.
Le sous-thème zen accomplit cela en ajoutant ceci à sa fonction theme_preprocess_node:
function foo_preprocess_node(&$variables, $hook) {
...
// Optionally, run node-type-specific preprocess functions, like
// foo_preprocess_node_page() or foo_preprocess_node_story().
$function = __FUNCTION__ . '_' . $variables['node']->type;
if (function_exists($function)) {
$function($variables, $hook);
}
...
}
Si vous avez un type de contenu appelé 'news', vous pourrez alors créer une fonction appelée foo_preprocess_node_news dans votre fichier template.php.
Je viens juste d'avoir un problème similaire c'est pourquoi google m'a amené à cette page: ma fonction de prétraitement de noeud grandissait tellement énormément, que je préfère diviser la fonction dans plusieurs fichiers.
J'ai déjà fait une approche similaire dans mon fichier template.php qui contient toutes les fonctions alter, et puisque la même méthode fonctionne parfaitement bien ici, j'ai pensé partager mon approche:
configuration du fichier dans le dossier MYTHEME/preprocess
:
- node.preprocess.inc
- node--blog-post.preprocess.inc
- node--device-variation.preprocess.inc
- (...)
vous devriez déjà avoir node.preprocess.inc
, les autres que vous pouvez créer vous-même. la façon dont vous les appelez est vraiment plutôt arbitraire, mais il vaut mieux leur donner des noms qui les identifient bien et qui correspondent à l'ensemble du système de nommage drupal.
au contenu de ces fichiers!
node.preprocess.inc
, ici je fais quelque chose comme ça:
<?php
function MYTHEME_preprocess_node(&$variables) {
switch($variables['type']) {
case 'blog_post':
// if the type of the node is a Blog Post, include this:
include 'node--blog-post.preprocess.inc';
break;
case 'device_variation':
// if Device Variation, include this:
include 'node--device-variation.preprocess.inc';
break;
case 'foo':
// ...
break;
}
// additional stuff for all nodes
}
nous passons essentiellement par le type du nœud actuel. ce que vous changez dépend de vous; #id
, #view_mode
, tout cela en fonction de vos besoins exacts.
une fois qu'il y a correspondance, il chargera le fichier spécifié et agira sur son contenu comme s'il avait été écrit directement dans cette fonction.
le contenu de ces fichiers included
ressemble exactement à ce que vous auriez mis dans le node.preprocess.inc
fichier, sauf que nous n'appelons pas à nouveau la fonction de prétraitement:
node--device-variation.preprocess.inc
<?php
// Device Name
$device = drupal_clean_css_identifier(strtolower($variables['title']));
// Determine whether only Device Version is of type 'N/A' and set ppvHasVariations accordingly
$deviceHasVariations = true;
if( $variables['content']['product:field_model_variation'][0]['#options']['entity']->weight == 0 ) {
$deviceHasVariations = false;
}
//...
vous pouvez essentiellement le faire avec autant de fichiers que vous le souhaitez et même mettre en cascade plusieurs commutateurs, par exemple en divisant davantage des fichiers de prétraitement de nœuds spécifiques en fonction du #view_mode
, ayant un fichier pour le mode d'affichage full
et un autre pour le teaser
j'espère que cela vous aidera, si quelqu'un bute à nouveau sur cette question (:
Dans votre hook_preprocess_node principal Implémentez le code suivant à la fin
$preprocess_function = 'themename_node__' . $node->type . '__preprocess';
if (function_exists($preprocess_function)) {
$preprocess_function($variables);
}
Vous devez donc prétraiter maintenant par type de nœud
call_user_func()
ne transmet pas les paramètres par référence. Ainsi, dans le cas de $variables
, Vos fonctions preprocess_foo()
fonctionneront uniquement sur les copies du tableau d'origine; les modifications sur les non-objets ne s'appliqueront pas pendant le processus de rendu restant.