
Twig 最佳實踐 - 預處理函數和模板

為了使 Drupal 8 的主題設計盡可能地維持高效率,並在 Twig 模板中允許進行更多自定義,請遵循以下最佳實踐:
從預處理函數返回渲染陣列 - Return render arrays from preprocess functions
在模板中調用過濾器和實用函數 - Call filters and utility functions in templates
本指南旨在協助具有 Drupal 7 經驗的 Drupal 開發人員,他們正試圖移除在 Drupal 8+ 中不再使用的 theme() 或 drupal_render() 等函數。這裡的 “Before” 示例通常以 Drupal 7 的代碼風格為例。
如果希望透過 Twig 進行更多可呈現的其他選擇,請考慮使用 twig_tweak 貢獻模組。詳情請見:consider the twig_tweak
從預處理函數返回渲染陣列
在預處理函數中,請始終返回渲染陣列,而不是調用 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'];
在模板中調用過濾器和實用函數
雖然渲染陣列透過模板為數據提供了一個可訪問且可修改的結構,但並非所有變數都需要渲染陣列。為了在模板中盡可能地長時間提供原始數據,主題開發人員應該在 Twig 模板內調用過濾器 filters,如 t,以及實用函數 utility functions,如 url()。在 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')));
In the template:
<p>{{ no_content_text }}</p>
After:
在 Twig 模板中:
<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 file):
<?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(預處理):
<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>

Twig 最佳實踐 - 預處理函數和模板

為了使 Drupal 8 的主題設計盡可能地維持高效率,並在 Twig 模板中允許進行更多自定義,請遵循以下最佳實踐:
從預處理函數返回渲染陣列 - Return render arrays from preprocess functions
在模板中調用過濾器和實用函數 - Call filters and utility functions in templates
本指南旨在協助具有 Drupal 7 經驗的 Drupal 開發人員,他們正試圖移除在 Drupal 8+ 中不再使用的 theme() 或 drupal_render() 等函數。這裡的 “Before” 示例通常以 Drupal 7 的代碼風格為例。
如果希望透過 Twig 進行更多可呈現的其他選擇,請考慮使用 twig_tweak 貢獻模組。詳情請見:consider the twig_tweak
從預處理函數返回渲染陣列
在預處理函數中,請始終返回渲染陣列,而不是調用 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'];
在模板中調用過濾器和實用函數
雖然渲染陣列透過模板為數據提供了一個可訪問且可修改的結構,但並非所有變數都需要渲染陣列。為了在模板中盡可能地長時間提供原始數據,主題開發人員應該在 Twig 模板內調用過濾器 filters,如 t,以及實用函數 utility functions,如 url()。在 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')));
In the template:
<p>{{ no_content_text }}</p>
After:
在 Twig 模板中:
<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 file):
<?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(預處理):
<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>