Funzione di preelaborazione per tipo di contenuto


25

Ho un paio di tipi di contenuto che devo preelaborare in diversi modi. Quindi template.phpnel mio tema fooattualmente appare come:

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) {
    ...
}

Vorrei poter specificare una funzione di pre-elaborazione specifica di Drupal che si agganciasse al nome della macchina del tipo di contenuto. Ho provato ad usare foo_preprocess_newsma non viene mai chiamato.

Esiste un modo migliore?

Risposte:


10

Il nome della funzione di preelaborazione si basa sul nome del tema, quindi per theme_table()la funzione di preelaborazione è MYTHEME_preprocess_table().

Poiché non esiste alcuna theme_node_node_typefunzione, un hook di preelaborazione come foo_preprocess_newso foo_preprocess_node_newsnon funzionerà immediatamente.

Si potrebbe andare circa l'override del Registro di tema in modo che esso comporta in modo diverso per i nodi, ma io davvero non lo consiglio; potrebbe diventare molto disordinato.

Sono un grande fan del codice di refactoring ma nel tuo caso non penso sia necessario; se hai una logica complessa che deve essere eseguita nel tuo hook di pre-elaborazione in base al tipo di nodo, coltivarla in diverse funzioni nel modo in cui stai facendo mi sembra una buona pratica.

L'altro metodo, ovviamente, sarebbe quello di implementare un modulo personalizzato per ciascuno dei diversi tipi di contenuto e implementare hook_preprocess_node()in ciascuno. In questo modo, la funzione di preelaborazione di ciascun modulo può essere responsabile di un diverso tipo di contenuto.

Tuttavia, questo può essere eccessivo per la tua situazione; se non si dispone di una logica aggiuntiva (ovvero una logica di preelaborazione non tematica) da eseguire su ciascun tipo di contenuto, questo metodo probabilmente non aggiunge alcun valore aggiuntivo.


1
OK. Potrei anche "automatizzare" foo_preprocess_nodeimplementandolo come call_user_func('_preprocess_' . $vars['type'], $vars);per evitare di ripetere l'if, ma probabilmente è meglio rimanere semplici.
Cherouvim,

Ho implementato hook_preprocess_node()un modulo personalizzato e speravo che si limitasse quando viene chiamato l'hook, ma non lo fa. Qualche modo per limitare quando l'hook viene chiamato dal tipo di contenuto?
Keven,

@Keven Non puoi impedire che venga invocata se esiste la funzione, ma if ($vars['node']->type == 'foo') { ...otterrai l'effetto che stai cercando
Clive

Sto solo cercando lievi ottimizzazioni, simili a quelle che puoi fare hook_block_view_MODULE_DELTA_alter(). Attualmente faccio quello che dici, ma vorrei che ci fosse un modo per limitare quando l'amo viene colpito.
Keven,

Non sarebbe un'ottimizzazione, anche se @Keven - trasferiresti il ​​processo decisionale su un'altra parte del codice. In effetti, se Drupal offrisse una tale sostituzione, dovrebbe essere generico e richiederebbe quasi sicuramente più tempo per il processore. Stai già vincendo prendendo la decisione solo all'ultimo momento
Clive

28

Il sottotema zen realizza questo aggiungendo questo alla sua funzione 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);
  } 
  ...
}

Se hai un tipo di contenuto chiamato 'news', allora saresti in grado di creare una funzione chiamata foo_preprocess_node_news nel tuo file template.php.


Lo usiamo anche su ZURB con la nostra impelementazione, frammento di codice molto utile.
Marko Blazekovic,

2

Ho appena avuto un problema simile , motivo per cui Google mi ha portato a questa pagina: la mia funzione di preelaborazione del nodo stava diventando così enormemente grande, che avrei preferito dividere la funzione in più file.

Ho già adottato un approccio simile nel mio file template.php che contiene tutte le funzioni alter, e poiché lo stesso metodo funziona perfettamente qui, ho pensato di condividere il mio approccio:

installazione file all'interno della cartella MYTHEME/preprocess:

- node.preprocess.inc
- node--blog-post.preprocess.inc
- node--device-variation.preprocess.inc
- (...)

dovresti già avere node.preprocess.inc, gli altri puoi creare te stesso. il modo in cui li chiami è piuttosto arbitrario, ma è meglio dare loro nomi che li identificano bene e si adattino all'intero sistema di denominazione drupal.
in seguito al contenuto di questi file!

node.preprocess.inc, qui sto facendo qualcosa del genere:

<?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

}

passiamo sostanzialmente attraverso il tipo del nodo corrente. ciò che passi attraverso dipende da te; #id, #view_modetutto a seconda delle tue esatte esigenze.
una volta che c'è una corrispondenza, caricherà il file specificato e agirà sul suo contenuto proprio come se fosse scritto proprio all'interno di questa funzione.

il contenuto di questi includedfile sembra esattamente come lo avresti inserito nel node.preprocess.incfile, tranne per il fatto che non chiamiamo nuovamente la funzione di preelaborazione:

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;
    }
    //...

puoi praticamente farlo con tutti i file che vuoi e persino mettere in cascata più switch, ad esempio suddividendo ulteriormente i file di preelaborazione di nodi specifici a seconda del #view_mode, avendo un file per la fullmodalità di visualizzazione e un altro per ilteaser

spero che questo aiuti, se qualcuno dovesse mai inciampare di nuovo su questa domanda (:


1

call_user_func()non passa parametri per riferimento. Quindi, nel caso in cui le $variablestue preprocess_foo()funzioni funzionino solo su copie dell'array originale; le modifiche su non oggetti non verranno applicate durante il restante processo di rendering.


1

Nel tuo hook_preprocess_node principale Implementa il seguente codice alla fine

$preprocess_function = 'themename_node__' . $node->type . '__preprocess';
if (function_exists($preprocess_function)) {
 $preprocess_function($variables);
}

Quindi avresti ora preelaborato per tipo di nodo

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.