Vorverarbeitungsfunktion pro Inhaltstyp

25

Ich habe einige Inhaltstypen, die ich auf unterschiedliche Weise vorverarbeiten muss. Also template.phpin meinem Theme foosieht das aktuell so aus:

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

Ich möchte in der Lage sein, eine Drupal-spezifische Vorverarbeitungsfunktion anzugeben, die sich auf den Computernamen des Inhaltstyps bezieht. Ich habe versucht mit, foo_preprocess_newsaber es wird nie aufgerufen.

Gibt es einen besseren Weg?

Cherouvim
quelle

Antworten:

10

Der Name der Vorverarbeitungsfunktion basiert auf dem Themennamen, für theme_table()Ihre Vorverarbeitungsfunktion also MYTHEME_preprocess_table().

Da es keine theme_node_node_typeFunktion gibt, funktioniert ein Vorverarbeitungs-Hook wie foo_preprocess_newsoder foo_preprocess_node_newsnicht sofort.

Sie könnten die Themenregistrierung überschreiben, damit sie sich für Knoten anders verhält, aber ich würde sie wirklich nicht empfehlen. es könnte sehr unordentlich werden.

Ich bin ein großer Fan von Refactoring-Code, aber in Ihrem Fall glaube ich nicht, dass es notwendig ist. Wenn Sie eine komplexe Logik haben, die abhängig vom Knotentyp in Ihrem Vorverarbeitungs-Hook ausgeführt werden muss, ist es für mich eine gute Übung, diese auf verschiedene Funktionen zu übertragen.

Die andere Methode wäre natürlich, ein benutzerdefiniertes Modul für jeden der verschiedenen Inhaltstypen zu implementieren und hook_preprocess_node()in jedem zu implementieren . Auf diese Weise kann die Vorverarbeitungsfunktion jedes Moduls für einen anderen Inhaltstyp verantwortlich sein.

Dies kann jedoch für Ihre Situation übertrieben sein. Wenn Sie keine zusätzliche Logik (dh keine Themenvorverarbeitungslogik) für jeden Inhaltstyp haben, fügt diese Methode wahrscheinlich keinen zusätzlichen Wert hinzu.

Clive
quelle
1
OKAY. Ich könnte das auch "automatisieren", foo_preprocess_nodeindem ich es wie call_user_func('_preprocess_' . $vars['type'], $vars);folgt implementiere , um das Wiederholen der ifs zu vermeiden, aber es ist wahrscheinlich am besten, einfach zu bleiben.
Cherouvim
Ich habe hook_preprocess_node()ein benutzerdefiniertes Modul implementiert und gehofft, dass dies den Aufruf des Hooks einschränken würde, aber nicht. Wie kann man einschränken, wann der Hook nach Inhaltstyp aufgerufen wird?
Keven,
@Keven Sie können nicht verhindern, dass es aufgerufen wird, wenn die Funktion vorhanden ist, aber Sie if ($vars['node']->type == 'foo') { ...erzielen den gewünschten Effekt
Clive
Ich bin wirklich nur auf der Suche nach leichten Optimierungen, ähnlich dem, was Sie damit machen können hook_block_view_MODULE_DELTA_alter(). Ich mache momentan, was du sagst, aber ich wünschte, es gäbe eine Möglichkeit zu beschränken, wann der Haken getroffen wird.
Keven,
Es wäre jedoch keine Optimierung, @Keven - Sie würden lediglich den Entscheidungsprozess auf einen anderen Teil des Codes verlagern. Tatsächlich müsste Drupal einen solchen Override anbieten, der generisch wäre und mit ziemlicher Sicherheit mehr Prozessorzeit in Anspruch nehmen würde. Sie gewinnen bereits, wenn Sie die Entscheidung erst im letzten Moment treffen
Clive
28

Das Zen-Subthema erreicht dies, indem es dies zu seiner theme_preprocess_node-Funktion hinzufügt:

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

Wenn Sie einen Inhaltstyp namens 'news' haben, können Sie in Ihrer template.php-Datei eine Funktion namens foo_preprocess_node_news erstellen.

Böse E
quelle
Wir verwenden dies auch auf der Grundlage von ZURB mit unserem eigenen, sehr nützlichen Code-Snippet.
Marko Blazekovic
2

Ich hatte gerade ein ähnliches Problem , weshalb mich Google auf diese Seite brachte: Meine Node Preprocess-Funktion wuchs so enorm, dass ich die Funktion lieber in mehrere Dateien aufteilen würde.

Ich habe in meiner template.php-Datei bereits einen ähnlichen Ansatz verfolgt, der alle Änderungsfunktionen enthält, und da die gleiche Methode hier einwandfrei funktioniert, dachte ich, ich würde meinen Ansatz teilen:

Dateieinrichtung im Ordner MYTHEME/preprocess:

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

Sie sollten bereits node.preprocess.incdie anderen haben , die Sie selbst erstellen können. Wie Sie sie wirklich nennen, ist eher willkürlich, aber geben Sie ihnen besser Namen, die sie gut identifizieren und zum gesamten Drupal-Benennungssystem passen.
weiter zum Inhalt dieser Dateien!

node.preprocess.inc, hier mache ich so etwas:

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

}

Wir wechseln grundsätzlich durch den Typ des aktuellen Knotens. was du durchschaltest, liegt bei dir; #id, #view_modeAlle abhängig, auf Ihre genauen Bedürfnisse.
Sobald eine Übereinstimmung vorliegt, wird die angegebene Datei geladen und auf ihren Inhalt angewendet, als ob sie direkt in diese Funktion geschrieben worden wäre.

Der Inhalt dieser includedDateien sieht genauso aus, wie Sie ihn in die node.preprocess.incDatei eingefügt haben, außer dass die Vorverarbeitungsfunktion nicht erneut aufgerufen wird:

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

Sie können dies im Grunde mit so vielen Dateien tun, wie Sie möchten, und sogar mehrere Switches #view_modehintereinander fullschalten, zteaser

Ich hoffe, das hilft, sollte jemand jemals wieder über diese Frage stolpern (:

Vogelkind
quelle
1

call_user_func()Übergibt keine Parameter als Referenz. Im Falle $variablesIhrer preprocess_foo()Funktionen können Sie also nur Kopien des ursprünglichen Arrays bearbeiten. Änderungen an Nicht-Objekten werden während des verbleibenden Rendervorgangs nicht übernommen.

Kishkash
quelle
1

Implementieren Sie in Ihrem main hook_preprocess_node den folgenden Code am Ende

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

Sie müssten also jetzt nach Knotentyp vorverarbeiten

Ziftman
quelle