Skip to main content

Controller with Twig template

Submitted by admin on Wed, 03/04/2020 - 08:42

Drupal 8 教學 - 新增Controller當中我們已經建立了一個簡單的,會回傳hello world訊息的controller。

在上一個範例中我們透過回傳一個包含#markup標籤的drupal render array簡單的把一個短字串輸出至網頁上,現在我們要來更詳細的介紹從字串變數到HTML的過程。

在繼續下去之前我們假設大家對產生HTML模板的twig語法已經有了基本的了解,如果還不太熟悉的話可以參考Twig教學 - 基本語法

我們假設這次所使用的模組名稱叫做SimpleController_TwigTemplate,我們可以到這裡來先看看這篇範例的執行結果。

 

1. 建立info以及routing檔案

老生常談的部分,這邊的內容跟之前大同小異。畢竟重點在controller所回傳的render array。

name: SimpleController_TwigTemplate
description: A simple drupal controller demo.
package: Simple Examples
type: module
core: 8.x
SimpleController_TwigTemplate.example:
  path: '/demo/simple_controller_with_twig_template' 
  defaults: 
    _controller: '\Drupal\SimpleController_TwigTemplate\Controller\SimpleExampleController::print_example' 
    _title: 'A demo of how drupal controller works with twig template'
  requirements: 
    _permission: 'access content'

如果網站中包含前幾篇文章的範例,要注意routing檔案內第一行的route name,也就是上面的SimpleController_TwigTemplate.example不要直接複製過往的範例而跟之前的模組重複了,會導致找不到網頁。

 

2. 建立controller物件

如果routing檔案是上面複製來的,這份檔案的位置應該放在[ModuleRoot]/src/Controller/SimpleExampleController.php。

<?php

namespace Drupal\SimpleController_TwigTemplate\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * An example controller.
 */
class SimpleExampleController extends ControllerBase {

  /**
   * Returns a render-able array for a test page.
   */
  public function print_example() {
      
      //Do something with your variables here.
      $myText = 'This is not just a default text!';
      $myNumber = 1;
      $myArray = [1, 2, 3];
      
      return array(
          //Your theme hook name
          '#theme' => 'my_example_template_A',
          //Your variables
          //'#variable1' => $myText,
          '#variable2' => $myNumber,
          '#variable3' => $myArray,
      );
  }

}

可以看到跟上次不一樣的地方在於回傳的render array。這次我們有了#theme來指定這個render array要透過何種轉換規則來變成最後的HTML,另外#variable1在這邊是故意註解掉的,這是因為我們等等要為變數設立預設值,我們可以透過不傳入該變數的方式來觀察變數預設值是否有生效。

 

3.建立twig template

唯一跟php比較沒關係的部分,但懂一點HTML的話應該看的出來在幹嘛。下方的內容要放在[ModuleRoot]/templates/my-example-template.html.twig裡面,如果希望放置在不同的位置或是不同的檔案名稱,可以在第四步的hook theme中設定。

twig語法部分可以先記住{{}}是印出變數,{%%}是執行運算邏輯就好。

<!-- Let's output the three variables passed to this template -->

<h2>My lovely twig template.</h2>
<p>You passed this text: <b>{{ variable1 }}</b></p>
<p>You passed this number value: {{ variable2 }}</p>
<p>And you passed this array:</p>

<ul>
    {% for item in variable3 %}
    <li>
       {{ item }} 
    </li>        
    {% endfor %}    
</ul>

</p>Ciao!</p>

請注意上面所使用的變數名稱必須與controller以及等等提到的hook theme保持一致。

 

4.定義hook_theme函式

hook_theme定義在module檔案內,位置在[ModuleRoot]/SimpleController_TwigTemplate.module

<?php

/**
 * Implements hook_theme().
 */
function SimpleController_TwigTemplate_theme($existing, $type, $theme, $path) {

  return [		
    //Name of the theme hook. This is used in the controller to trigger the hook.
    'my_example_template_A' => [
      //If no template name is defined here, it defaults to the name of the theme hook, ie. 'my-example-template.html.twig
      'template' => 'my-example-template',
      //Optionally define path to Twig template files. Defaults to the module's ./templates/ directory.
      'path' => $path . '/templates',
      //Optionally define variables that will be passed to the Twig template and set default values for them.
      'variables' => [
          'variable1' => 'Yet another default text.',
          'variable2' => 0,
          'variable3' => [0, 0, 0],
      ],
    ],
  ];

}

有興趣的話可以看一下Drupal官方文件對於hook_theme的描述。裡面開宗明義的第一行就是:

The implementations declared by this hook specify how a particular render array is to be rendered as HTML.

換言之,hook_theme描述了render array轉換成HTML的過程,其中包含了要使用哪個twig template,我們可以透過上方的template以及path鍵值來指定這點。my_example_template_A則跟我們在contorller中所回傳的 '#theme' 值相對應。

variables陣列裡面的鍵是變數名稱,值則是來是controller的render array找不到值時的預設值,因為我們在controller內把#variable1註解掉了,所以最後看到的內容是由hook_theme提供的預設值。注意這邊的variables描述的是要送進twig template內的變數定義而不是一個render array,所以變數名稱必須要是一個合法的php/twig變數名稱,也不需要以「#」符號開頭。

 

enjoy~