Twigのベストプラクティス - 前処理関数とテンプレート
Drupal 8のテーマ設定を可能な限り効率的にし、Twigテンプレートでより多くのカスタマイズオプションを提供するには、次の推奨事項に従ってください:
このガイドは、Drupal 7の経験があり、Drupal 8以降で使用すべきでなくなったtheme()やdrupal_render()などの関数を削除しようとしているDrupal開発者を支援するために書かれています。ここでの「Before」の例は、一般的にDrupal 7のコードスタイルで書かれています。
前処理関数からレンダリング配列を返す
前処理関数でtheme()やdrupal_render()を呼び出す代わりに、常にレンダリング配列を返します。
Twigはすべてを自動的にレンダリングするため、前処理関数内でdrupal_render()やtheme()を呼び出す必要はありません。代わりに、レンダリング配列をテンプレートに渡す必要があります。これにより、すでにレンダリングされたHTML文字列よりもはるかに多くのカスタマイズが可能になります。
前処理関数からのtheme()の削除:
// Before - passing a string of rendered HTML to the template.
$variables['table'] = theme('table', ['header' => $header, 'rows' => $rows]);
// After - passing a render array to the template.
$variables['table'] = [
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
];
前処理関数からdrupal_render()を削除するのは、呼び出しを削除するだけの問題です:
// Before, unnecessary call to drupal_render().
$variables['teaser'] = drupal_render($node_teaser);
// After, with drupal_render() removed.
$variables['teaser'] = $node_teaser;
drupal_render()がテーブルデータに追加されたときに呼び出されることは一般的です。
// Before, unnecessary call to drupal_render().
$row[] = drupal_render($display['title']);
// After, with drupal_render() removed.
$row[]['data'] = $display['title'];
テンプレートでフィルターとユーティリティ関数を呼び出す
レンダリング配列はテンプレートまでのデータのアドレス指定可能で変更可能な構造を提供しますが、すべての変数にレンダリング配列が必要なわけではありません。生データをできるだけ長くテンプレートに提供するために、テーマ開発者はフィルター(tなど)やurl()などのユーティリティ関数をTwigテンプレートから呼び出す必要があります。前処理関数ではなくTwigテンプレートでこれらの関数を呼び出すと、テンプレートに渡される変数がテンプレートで出力されない可能性があるため、関数呼び出しを減らすことができます。
Before:
前処理関数内:
$variables['no_content_text'] = t('You have not created any content types yet. Go to the <a href="@create-content">content type creation page</a> to add a new content type.', array('@create-content' => url('admin/structure/types/add')));
テンプレート内:
<p>{{ no_content_text }}</p>
After:
テンプレート内:
<p>{{ 'You have not created any content types yet. Go to the <a href="@create-content">content type creation page</a> to add a new content type.'|t({'@create-content': url('admin/structure/types/add')}) }}</p>
表示/非表示、drupal_render_childrenとelement_childrenの削除
元のテンプレートでhide()が呼び出され、drupal_render_childrenがデータの「残り」のレンダリングに使用されていた場合、前処理中にこれらすべてを個別の変数に分割する必要があります。
Before(PHPTemplateファイル):
<?php
hide($form['advanced']);
hide($form['actions']);
?>
<div class="layout-node-form clearfix">
<div class="layout-region layout-region-node-main">
<?php print drupal_render_children($form); ?>
</div>
<div class="layout-region layout-region-node-secondary">
<?php print render($form['advanced']); ?>
</div>
<div class="layout-region layout-region-node-footer">
<?php print render($form['actions']); ?>
</div>
</div>
特定の要素を非表示にするには、「without」と呼ばれるTwigフィルターを使用します。必要に応じて、それらを通常どおりレンダリングできます。
After:(Twigテンプレート)
<div class="layout-node-form clearfix">
<div class="layout-region layout-region-node-main">
{{ form|without('advanced', 'actions') }}
</div>
<div class="layout-region layout-region-node-secondary">
{{ form.advanced }}
</div>
<div class="layout-region layout-region-node-footer">
{{ form.actions }}
</div>
</div>
代替方法(もう必要ありません):
すべてを個別の変数に前処理してテンプレートに渡します。残りをレンダリングする前に、レンダリングするものを要素全体(この場合はフォーム)から変数に分割する必要があるかもしれません。コンテンツをテンプレートで意図されたとおりに正確に出力します。
Before:(前処理)
function template_preprocess_node_edit_form(&$variables) {
$form = $variables['form'];
// @todo Update this once drupal.org/node/1920886 is resolved.
$variables['advanced'] = $form['advanced'];
$variables['actions'] = $form['actions'];
unset($form['advanced'], $form['actions']);
$variables['form'] = drupal_render_children($form);
}
After:(Twigテンプレート)
<div class="layout-node-form clearfix">
<div class="layout-region layout-region-node-main">
{{ form }}
</div>
<div class="layout-region layout-region-node-secondary">
{{ advanced }}
</div>
<div class="layout-region layout-region-node-footer">
{{ actions }}
</div>
</div>