[Drupal Theming] Twig Variables 的一些用法

最近在處理 template 時遇到一些困難:我的 taxonomy term 有一個單值的 media 欄位:field_media,我想把儲存於其中的圖檔 uri 抓出來,在 template 裡當作另一元素的背景圖片。這在 Drupal 裡,其實就是印出變數,可參見 Hello!Santa 提供的典型範例

一、基本用法

我們可以從最常用到、預設功能也最豐富的 entity type:node 來看看變數這回事。以下是在 node.html.twig 可使用的,非常多樣的變數:

{#
/**
* @file
* Bootstrap Barrio's theme implementation to display a node.
*
* Available variables:
* - node: The node entity with limited access to object properties and methods.
Only "getter" methods (method names starting with "get", "has", or "is")
and a few common methods such as "id" and "label" are available. Calling
other methods (such as node.delete) will result in an exception.
* - label: The title of the node.
* - content: All node items. Use {{ content }} to print them all,
*   or print a subset such as {{ content.field_example }}. Use
*   {{ content|without('field_example') }} to temporarily suppress the printing
*   of a given child element.
* - author_picture: The node author user entity, rendered using the "compact"
*   view mode.
* - metadata: Metadata for this node.
* - date: Themed creation date field.
* - author_name: Themed author name field.
* - url: Direct URL of the current node.
* - display_submitted: Whether submission information should be displayed.
* - attributes: HTML attributes for the containing element.
*   The attributes.class element may contain one or more of the following
*   classes:
*   - node: The current template type (also known as a "theming hook").
*   - node--type-[type]: The current node type. For example, if the node is an
*     "Article" it would result in "node--type-article". Note that the machine
*     name will often be in a short form of the human readable label.
*   - node--view-mode-[view_mode]: The View Mode of the node; for example, a
*     teaser would result in: "node--view-mode-teaser", and
*     full: "node--view-mode-full".
*   The following are controlled through the node publishing options.
*   - node--promoted: Appears on nodes promoted to the front page.
*   - node--sticky: Appears on nodes ordered above other non-sticky nodes in
*     teaser listings.
*   - node--unpublished: Appears on unpublished nodes visible only to site
*     admins.
* - title_attributes: Same as attributes, except applied to the main title
*   tag that appears in the template.
* - content_attributes: Same as attributes, except applied to the main
*   content tag that appears in the template.
* - author_attributes: Same as attributes, except applied to the author of
*   the node tag that appears in the template.
* - title_prefix: Additional output populated by modules, intended to be
*   displayed in front of the main title tag that appears in the template.
* - title_suffix: Additional output populated by modules, intended to be
*   displayed after the main title tag that appears in the template.
* - view_mode: View mode; for example, "teaser" or "full".
* - teaser: Flag for the teaser state. Will be true if view_mode is 'teaser'.
* - page: Flag for the full page state. Will be true if view_mode is 'full'.
* - readmore: Flag for more state. Will be true if the teaser content of the
*   node cannot hold the main body content.
* - logged_in: Flag for authenticated user status. Will be true when the
*   current user is a logged-in member.
* - is_admin: Flag for admin user status. Will be true when the current user
*   is an administrator.
*
* @see template_preprocess_node()
*/
#}

大家有興趣可以用 Devel - kint 把各個變數剝開看看,還滿有趣的。

假設我今天在 node.html.twig 裡寫下了: {{ content.field_media.0 }} ,翻譯成口語是這樣的:我要 printcontent 底下 field_media 欄位的第一個值

二、每個 template 提供的變數不太一樣

我們再打開 taxonomy-term.html.twig 來看,發現變數的數量少很多:

{#
/**
* @file
* Theme override to display a taxonomy term.
*
* Available variables:
* - url: URL of the current term.
* - name: Name of the current term.
* - content: Items for the content of the term (fields and description).
*   Use 'content' to print them all, or print a subset such as
*   'content.description'. Use the following code to exclude the
*   printing of a given child element:
*   @code
*   {{ content|without('description') }}
*   @endcode
* - attributes: HTML attributes for the wrapper.
* - page: Flag for the full page state.
* - term: The taxonomy term entity, including:
*   - id: The ID of the taxonomy term.
*   - bundle: Machine name of the current vocabulary.
* - view_mode: View mode, e.g. 'full', 'teaser', etc.
*
* @see template_preprocess_taxonomy_term()
*/
#}

三、如果你願意一層一層 一層的剝開我的變數

回到開頭,我要抓出 media 欄位裡儲存的圖檔uri,但用 {{ content.field_media.0 }} 會把整個 media entity 都印出來(可能不只一個欄位)。我該怎麼找出單純的 uri 呢?就要用 kint 一層一層剝開了: {{ kint(content.field_media.0 }}

最後剝出來的結果是這樣: {{ content.field_media.0['#item'].entity.uri.value }}

如果要檔案的相對位址的話,則是 {{ file_url(content.field_fea.0['#item'].entity.uri.value) }}

四、小提示

  1. 我們用 {{ kint() }} {{ kint(content) }} 的時候,很有可能會使頁面變成一片空白。這是 kint 造成記憶體不足的緣故,因此我們要限制 kint 的顯示層級,作法可參考這篇
  2. 更多 Twig 的基本概念可參考這篇,以及 Drupal 官方文件
  3. Twig debug 說明請見官方文件;神器 Devel - Kint 的教學請見這篇