コンテンツタイプごとの前処理機能


25

さまざまな方法で前処理する必要があるコンテンツタイプがいくつかあります。したがってtemplate.php、私のテーマではfoo現在次のようになっています。

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

コンテンツタイプのマシン名をフックするDrupal固有の前処理関数を指定できるようにしたいと思います。使用してみましたfoo_preprocess_newsが、呼び出されることはありません。

もっと良い方法はありますか?

回答:


10

前処理関数の名前はテーマ名に基づいているためtheme_table()、前処理関数の名前はMYTHEME_preprocess_table()です。

そこにはありませんので、theme_node_node_type関数のような前処理のフックfoo_preprocess_newsfoo_preprocess_node_news、箱から出して動作しません。

テーマレジストリをオーバーライドして、ノードに対して異なる動作をさせることもできますが、実際にはお勧めしません。非常に面倒になります。

私はコードのリファクタリングの大ファンですが、あなたの場合、それは必要だとは思いません。ノードタイプに依存するプリプロセスフックで実行する必要がある複雑なロジックがある場合、現在の方法で異なる機能にファームアウトすることは、私にとって良い習慣のようです。

もちろん、他の方法は、異なるコンテンツタイプごとにカスタムモジュールを実装しhook_preprocess_node()、それぞれに実装することです。そのようにして、各モジュールの前処理関数は、異なるコンテンツタイプを担当できます。

ただし、これは状況によってはやり過ぎかもしれません。各コンテンツタイプで実行する追加のロジック(テーマ以外の前処理ロジックなど)がない場合、このメソッドはおそらく追加の値を追加しません。


1
OK。ifの繰り返しを避けるためにfoo_preprocess_node実装することで「自動化」することもできますcall_user_func('_preprocess_' . $vars['type'], $vars);が、おそらくシンプルに保つことが最善です。
-cherouvim

hook_preprocess_node()はカスタムモジュールに実装し、フックが呼び出されるタイミングを制限することを望んでいましたが、そうではありませんでした。コンテンツタイプによってフックが呼び出されるタイミングを制限する方法はありますか?
ケベン

@Keven関数が存在する場合、呼び出されるのを止めることはできませんが、if ($vars['node']->type == 'foo') { ...探している効果は得られます
クライブ

私はあなたができることと同様に、わずかな最適化を本当に探していますhook_block_view_MODULE_DELTA_alter()。現在、私はあなたの言うことをしていますが、フックがヒットするタイミングを制限する方法があればいいのにと思います。
ケベン

@Kevenですが、最適化ではありません-意思決定プロセスをコードの別の部分にシフトしているだけです。実際、Drupalがそのようなオーバーライドを提供する場合、汎用である必要があり、ほぼ確実に達成するためにより多くのプロセッサー時間がかかります。あなたはすでに最後の瞬間に決定を下すだけで勝利しています
クライブ

28

zenサブテーマは、これを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);
  } 
  ...
}

「news」というコンテンツタイプがある場合は、template.phpファイルにfoo_preprocess_node_newsという関数を作成できます。


また、独自の実装、非常に便利なコードスニペットでZURB基盤でこれを使用します。
マルコブラゼコビッチ

2

私は同様の問題を抱えていたので、Googleがこのページに連れて行ったのはなぜですか:ノードのプリプロセス関数が非常に大きく成長しているため、関数を複数のファイルに分割したいです。

すべてのalter関数を含むtemplate.phpファイルで同様のアプローチを既に実行しましたが、ここでは同じメソッドが完全に機能するため、アプローチを共有すると思いました。

フォルダー内のファイル設定MYTHEME/preprocess

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

既にnode.preprocess.inc作成されている必要があります。それらを実際に呼び出す方法はかなりarbitrary意的ですが、それらを適切に識別し、drupalネーミングシステム全体に適合する名前を付ける方がよいでしょう。
これらのファイルのコンテンツに進んでください!

node.preprocess.inc、ここで私はこのようなことをしています:

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

}

基本的に現在のノードのタイプを切り替えます。切り替えるのはあなた次第です。#id#view_mode、すべてのあなたの正確なニーズに応じました。
一致が見つかると、指定されたファイルをロードし、この関数内で記述されているかのようにその内容を処理します。

これらのincludedファイルの内容はnode.preprocess.inc、前処理関数を再度呼び出さないことを除いて、ファイルに配置した場合とまったく同じです。

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

あなたがしたいとさえ複数のスイッチをカスケード接続すると、あなたは基本的には、たとえば、など多くのファイルとに応じて、特定のノードの前処理ファイルをバックアップし、さらに分割を行うことができます#view_modeいずれかのファイルを持つ、fullビューモードとのために別のものをteaser

誰かがこの質問に再びつまずいたら、これが役立つことを願っています(:


1

call_user_func()参照によってパラメーターを渡しません。だから、の場合には$variables、あなたのpreprocess_foo()機能だけで元の配列のコピーで動作します。非オブジェクトの変更は、残りのレンダリングプロセス中には適用されません。


1

メインのhook_preprocess_nodeで、最後に次のコードを実装します

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

したがって、ノードタイプごとに前処理することになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.