モジュールディレクトリでテンプレートを探すようにDrupalに指示する方法


11

モジュールにテンプレート実装を提供し、テーマがそれをオーバーライドできるようにしたいと思います。基本的に、私はこの簡略化されたコードによる提案を追加します:

function attach_preprocess_node(&$vars) {
  $vars['theme_hook_suggestions'][] = 'node__test';
}

(プリプロセスノード関数を再利用したいので、hook_themeを使用して新しいテーマを追加したくありません。テーマ名は扱いにくいですが、ノードタイプとの混同を避けるためにnode_ attach _%を記述したくありません。)

次に、hook_theme_registry_alter()を使用してモジュールパスを追加します。

function attach_theme_registry_alter(&$theme_registry) {
  $path = drupal_get_path('module', 'attach') . '/themes';
  $theme_registry_copy = $theme_registry;
  _theme_process_registry($theme_registry_copy, 'phptemplate', 'theme_engine', 'node', drupal_get_path('module', 'node'));
  $theme_registry += array_diff_key($theme_registry_copy, $theme_registry);
  if (!isset($theme_registry['node']['theme paths'])) {
    $theme_registry['node']['theme paths'] = array();
  }
  if (!isset($theme_registry['node']['theme paths'])) {
    $first_element = array_shift($theme_registry['node']['theme paths']);
    if ($first_element) {
      array_unshift($theme_registry['node']['theme paths'], $first_element, $path);
    }
    else {
      array_unshift($theme_registry['node']['theme paths'], $path);
    }
  }
}

ただし、機能しません。つまり、themes / node--super.tpl.phpファイルは使用されません。テーマフォルダにコピーした場合にのみ使用されます。


明確化:コードで定義されたテンプレート(ここではノードテンプレート)のモジュールディレクトリ(およびテーマディレクトリ)をDrupalで調べてほしい。新しいテンプレートを定義したくありません。
jcisio 2012

回答:


5

基本的にhook_theme()、レジストリを変更する代わりに実装することで、少し頭痛の種を省くことができます。

このAPIドキュメントページで手軽に再現したExamplesプロジェクトの theming_exampleをご覧になることをお勧めしますこのページに特に役立つコードが含まれている可能性があります

function theming_example_list_page() {
  $items = array(
    t('First item'),
    t('Second item'),
    t('Third item'),
    t('Fourth item'),
  );

  // First we'll create a render array that simply uses theme_item_list.
  $title = t("A list returned to be rendered using theme('item_list')");
  $build['render_version'] = array(
    // We use #theme here instead of #theme_wrappers because theme_item_list()
    // is the classic type of theme function that does not just assume a
    // render array, but instead has its own properties (#type, #title, #items).
    '#theme' => 'item_list',
    // '#type' => 'ul',  // The default type is 'ul'
    // We can easily make sure that a css or js file is present using #attached. 
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')), 
    '#title' => $title, 
    '#items' => $items, 
    '#attributes' => array('class' => array('render-version-list')),
  );

  // Now we'll create a render array which uses our own list formatter,
  // theme('theming_example_list').
  $title = t("The same list rendered by theme('theming_example_list')");
  $build['our_theme_function'] = array(
    '#theme' => 'theming_example_list', 
    '#attached' => array('css' => array(drupal_get_path('module', 'theming_example') . '/theming_example.css')), 
    '#title' => $title, 
    '#items' => $items,
  );
  return $build;
}

これはDrupal 7のすべてです。


質問で述べたように、ノードテンプレートで$ variablesを再利用するため、hook_theme()は使用しません。これらの変数は、テーマの存在(定義した場合)を知らない多くのモジュールのhook_(pre)プロセスで生成されます。
jcisio

テーマを定義する方法は、... hook_theme()を使用することです。:-) hook_theme()でテーマ関数を定義できます。好きな名前を付けます。必要に応じてシム関数を作成します。APIドキュメント:「hook_theme_HOOK()...モジュールが定義していないテーマフックのテーマ前処理をオーバーライドまたは追加する必要がある場合にのみ使用してください。」
paul-m

テーマを定義したくない。「node」を再利用する代わりにテーマ「mynode」を定義する場合、.tpl.phpファイルに変数はありません。
jcisio 2012年

1
これは本当のようではありません:テーマの呼び出しが実装ので、累積しているhook_themeあなたを与える必要があります$existingあなたはそれをオーバーライドしていない、事を変更することができますパラメータを。そうでない場合は、おそらくバグにぶつかっています。
Countzero

テーマnode_attachを宣言するときに@Countzeroを使用すると、すべてのhook_preprocess_node関数は新しいテーマでは実行されません。つまり、node-attach.tpl.phpには何もありません。
jcisio

5

多分これはうまくいきます:

/**
 * Implements hook_theme().
 */
function MODULE_theme($existing, $type, $theme, $path) {
  return array (
    'node__CONTENTTYPE' => array (
      'variables' => array( . . . ),
      'template' => 'node--CONTENTTYPE' ,
      'base hook' => 'node',
      'path' => drupal_get_path('module', 'MODULE'),
    ),
  );
}

ここで重要なのは、キー「ベースフック」です。


ドキュメントの追加に関する問題はbase hook次のとおり
Andy

+1賛成票-これと、私が機能することがわかったbatigotixからの派生的な回答。ありがとう。
therobyouknow 2015年

2

dashohoxhaによるhook_theme実装のソリューションが好きですが、機能させることができませんでした。さらにググリングした後、私にはうまくいくバリエーションが見つかりまし

/**
 * Implements hook_theme().
 */
function mymodule_theme($existing, $type, $theme, $path) {
  $theme = array();
  $theme['node__blog_post'] = array(
    'render element' => 'content',
    'base hook' => 'node',
    'template' => 'node--blog_post',
    'path' => drupal_get_path('module', 'mymodule') . '/templates',
   );
  return $theme;
}

注:カスタムモジュールは「mymodule」と呼ばれ、カスタムコンテンツタイプは「blog_post」と呼ばれます。私が使用するtpl.phpは 'node--blog_post.tpl.php'と呼ばれ、モジュールの 'templates'サブフォルダーにあります。


+1おかげで、これが機能することがわかりました。:あなたは、あなたのカスタムモジュール内のtemplate.php機能をオーバーライドに興味があるなら、見てみましょうsnugug.com/musings/override-theme-functions-drupal-7-module -私はこれは非常にうまく機能することが分かっ
therobyouknow

2

以下は、「custom_module」の「template」フォルダに格納されているビューテンプレートを宣言するためのスニペットです。

/**
 * Implements hook_theme_registry_alter().
 */
function custom_module_theme_registry_alter(&$theme_registry) {
  $extension   = '.tpl.php';
  $module_path = drupal_get_path('module', 'custom_module');
  $files       = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');

  foreach ($files as $file) {
    $template = drupal_basename($file->filename, $extension);
    $theme    = str_replace('-', '_', $template);
    list($base_theme, $specific) = explode('__', $theme, 2);

    // Don't override base theme.
    if (!empty($specific) && isset($theme_registry[$base_theme])) {
      $theme_info = array(
        'template'   => $template,
        'path'       => drupal_dirname($file->uri),
        'variables'  => $theme_registry[$base_theme]['variables'],
        'base hook'  => $base_theme,
        // Other available value: theme_engine.
        'type'       => 'module',
        'theme path' => $module_path,
      );

      $theme_registry[$theme] = $theme_info;
    }
  }
}

それが誰かを助けることを願っています。


時間を節約できました。d8にも
有効で必須

-1

Stack Overflowで一度尋ねました。基本的hook_theme_registry_alter()に、テーマフックテンプレートパスにパスを追加するには、実装する必要があります。次に、でdrupal_theme_rebuild()hook_enable()呼び出し てテーマレジストリキャッシュをクリアし、テンプレートのパスをスキャンします。


たぶん、あなたを阻んでいるのは単にキャッシュをクリアすることです。
Capi Etheriel 2012年

したがって、基本的には同じソリューションです。「drush cc all」を50回以上試し、新しいインストールサイトなどでテストしたところ、うまくいきませんでした。誰でもテストできるように、コードを変更して最小限のモジュールに圧縮します。
jcisio

hook_enable()モジュールが有効になると呼び出されます。モジュールがすでに有効になっている場合は、無効にしてから再度有効にする必要があります。
kiamlaluno

@kiamlaluno:hook_enableを使用してキャッシュをクリアします。すでにインストールされている場合、ユーザーは手動でキャッシュをクリアするだけです。
Capi Etheriel 2012年

いいえ、-1ポイント。その解決策は非常に古い(2009)ので、D7向けのものであったかどうかさえわかりません。古いソリューションはビュー用に調整されていますが、開発者がモジュール内のテーマキーごとに複数のデフォルトテンプレートをパックする必要があるビュー以外の状況には理想的ではありません。単一のテーマキーに対して100の動的テーマ提案のソリューションを実装することを想像してください。ビューのコンテキスト外で適用すると、私はあなたのソリューションをカウンターパターンと呼びます。
アマチュアバリスタ2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.