web-dev-qa-db-ja.com

テンプレートから別のテーマ変数を渡すにはどうすればよいですか?

ノード内のいくつかのフィールドは、その一部であるニュースレターの本文に応じて、特定の方法で表示する必要があります。囲みニュースレター本文から囲みフィールドに変数を渡して、フィールドにそのコンテキストを通知し、フィールドの表示方法を制御できるようにするにはどうすればよいですか?

ニュースレターの本文と本文に含まれるフィールドの両方の前処理機能を持つテーマがあります。

本文のプリプロセス関数とその関連するtwigテンプレート)に変数を設定したいのですが、フィールドのプリプロセス関数や独自のテンプレートで検査できます。

言い換えれば、各フィールドがレンダリングされている本文のコンテキストを認識できるようにしたいのです。

具体的には、テーマのsimplenews-newsletter-body.html.twigテンプレートで検査(および設定)できる変数(_$variables['summons'] = 'placeholder';_)を設定するmytheme_preprocess_simplenews_newsletter_body()がありますが、(別のレンダー配列)は、その後mytheme_preprocess_field()にも、field--node--title.html.twigにも表示されません。

2つのレンダーアレイ間の通信方法を教えてください。

ご了承ください

  1. _$db_is_active_や_$is_admin_のようなグローバル変数があるようです。

  2. 時には、CSSクラス属性を包含要素から包含要素にカスケードすることにより、この種のことを実現することが可能です。これは一般的には満足のいくものではなく、この特定のケースでは、CSSの予測できない扱いをさまざまなターゲットメールクライアントで実行することはありません。

6
iainH

私が取り組んでいるソリューションは drupal_static() ;を使用することです。以下のコードの簡略化された基本事項-&アンパサンドに注意してください。それは私がそれを必要とする場所を私に制御させています。

したがって、このアプローチを使用すると、フィールドごとに、グローバルコンテキストを考慮して、通常の方法で変数を設定できます。 mytheme_preprocess_field()で、その後field--node--title--agenda.html.twigのような関連テンプレートで使用されます

function mytheme_preprocess_simplenews_newsletter_body(&$variables) {
  // prepare to alter static var ...
  // get a reference binding to static var
  $var = &myvariable_function();
  // alter static var
  $var = 'simplenews_newsletter';
}

function mytheme_preprocess_field(&$variables, $hook) {
  // prepare to read static var
  // assign static var
  $var = myvariable_function();
  // $element is the render array for the field
  $element = $variables['element'];
  // filter those cases where it matters that we're theming a newsletter
  if ($element['#view_mode'] == 'email_html' and $var == 'simplenews_newsletter') {
    // Do stuff here like setting a variable for twig ...
    $variables['summons'] = 'some text';
  }
}
function &myvariable_function() {
  $var = &drupal_static(__FUNCTION__);
  if (!isset($var)) {
    // generate contents of static variable
    $var =  'initial_value';
  }
  return $var;
}

ページのレンダリング階層の異なるレベル間で共通のコンテキストを通信する他の方法があると確信しています。どのようにそれを行うか教えてください。

4
iainH

私はこのコードを使用します:

_/**
 * Helper function to pass slider variables from preprocess_page to preprocess_page_title_custom
 * @param  string $new_image Image URL
 * @return array             Images URL Array
 */
function _core_slider_images($new_image = NULL) {
  $vars = &drupal_static(__FUNCTION__, array());
  // If a new value has been passed add to the array.
  if ($new_image) {
    $vars[] = $new_image;
  }
  return $vars;
}
_

このテンプレートから:

_page.html.twig_では、$ node変数にアクセスできます。この変数にアクセスできない別のテンプレートに値を渡す必要があります。渡す必要がある値を検索し、_core_slider_images()を呼び出します。この関数は、2つのテンプレート(前処理関数)間のブリッジになります

_/**
 * Implements hook_preprocess_page().
 */
function MODULE_preprocess_page(&$variables) {
  // ...
  // Sending Images URL and titles from page to page_title.
    for ($i = 0; $i < $cant; $i++) {
      // Adding the images to the static function.
      _core_slider_images($variables['node']->field_image[$i]->entity->url());
    }
  }
_

このテンプレートに:

_page-title-custom.html.twig_はカスタムテンプレートであり、$ nodeへのアクセス権がありません。 hook_preprocess_page()が最初に呼び出されるので、静的変数に$ node値を格納し、_core_slider_images()関数を呼び出すだけで済みます。

_/**
 * Implements hook_preprocess_HOOK().
 */
function MODULE_preprocess_page_title_custom(&$variables) {
  // Searching the variables for sending to the page-title-custom template.
   $images = _core_slider_images();
}
_
1

私はまだD8に慣れていないので、簡単にトリックを見逃す可能性があります。通常、この状況では、変更したいすべてのものにアクセスできる最も具体的なフックを探します。したがって、フィールドレベルでの変更は具体的すぎ、ページレベルでの変更(たとえば)は一般的すぎます。

残念ながらMailEntityは実際の(Drupal)エンティティではないため、標準のフックを使用してレンダー配列を変更することはできません。コンテンツを変更できるようにするために表示されるカスタムフックも呼び出されません。この状況のD7では、ダーティですが機能すると思うhook_page_alter()を使用したくなりますが、D8から削除されました。

いつでもMailEntityクラスをオーバーライドして独自のカスタマイズを直接提供できますが、テーマの変更のためにそれを行う必要があるのは、私には少し間違っているようです。

0
Andy