Giới thiệu

Twig là một template engine cho PHP, được sử dụng trong rất nhiều framework khác nhau như Symfony, Drupal8, eZPublish, phpBB, Piwik, OroCRM và được hỗ trợ trong một vài framework khác, có thể kể đến Slim, Yii, Laravel, Codeigniter. Được thiết kế và phát triển dựa trên các nguyên tắc cơ bản của PHP dưới các tiêu chí : Fast, Secure, Flexible.

Cài đặt

Để cài đặt được Twig, phiên bản PHP của bạn phải là từ 5.2.7 trở lên. Có thể cài đặt Twig qua composer, rất đơn giản, chỉ cần gõ câu lệnh sau.
composer require twig/twig:~1.0

Hoặc bạn có thể tải trực tiếp từ trên git về .
git clone git://github.com/twigphp/Twig.git

Chúng ta có thể cài đặt thêm một số plugin trên IDE của mình để có thể làm việc hiệu quả hơn. Ví dụ như Sublime Text thì có thể cài Twig Bundle.
Đây là một vài cách để chúng ta có thể sẵn sàng làm việc với Twig.

Sử dụng cơ bản

Trong Twig, chúng ta sẽ sử dụng hai lọai kí hiệu, đó là {% … %} dùng để thực hiện các câu lệnh như vòng lặp hoặc điều kiện. Kí hiệu tiếp theo đó là {{ … }} dùng để in ra kết quả của biến hoặc biểu thức ra màn hình.

Variables

Twig hỗ trợ việc truy xuất các biến rất đơn giản, chỉ với dấu (.), chúng ta có thể lấy các giá trị của Object hoặc Array.

{{ foo.bar }}
{{ foo['bar'] }}

Trong trường hợp có kí tự đặc biệt, hàm attribute() có thể hỗ trợ chúng ta.

{{ attribute(foo, 'data-foo') }}

Với biến Global, chúng ta có thể sử dụng ở bất kì chỗ nào

  • _self : tham chiếu đến template hiện tại
  • _context : tham chiếu đến context hiện tại
  • _charset : tham chiếu đến charset hiện tại

Nếu cần thì bạn cũng có thể gán giá trị cho biến

{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}

Filters

Đây là một thứ rất hay của Twig, nó có thể giúp chúng ta tùy biến kết quả được hiển thị.

Number format lọc biến có giá trị number giống với hàm number_format của PHP.

{{ 200000|number_format }}

Hoặc có thể sắp xếp một mảng ngay tại template.

{% for number in numbers|sort %}
   {{ number }}
{% endfor %}

Tham khảo thêm tại Filters.

Named Arguments

Từ phiên bản 1.12, Twig bắt đầu hỗ trợ named arguments.

{% for i in range(low=1, high=10, step=2) %}
    {{ i }},
{% endfor %}

Sử dụng named arguments giúp cho template của bạn rõ ràng hơn khi truyền vào các đối số.

{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}

{# versus #}

{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}

Bạn cũng có thể cho phép bạn bỏ qua một số arguments mà bạn không muốn thay đổi giá trị mặc định.

{# the first argument is the date format, which defaults to the global date format if null is passed #}
{{ "now"|date(null, "Europe/Paris") }}

{# or skip the format value by using a named argument for the time zone #}
{{ "now"|date(timezone="Europe/Paris") }}

Hoặc sử dụng cả hai kiểu trong một lần gọi

{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}

Functions

Twig cũng hỗ trợ nhiều function cho chúng ta sử dụng, không hề khác với các ngôn ngữ lập trình nói chung.

Hàm dump() sẽ giúp chúng ta debug đơn giản hơn.

<pre>
    {{ dump(user) }}
</pre>

Và rất nhiều hàm khác ở Twig function.

Control Structure

Các câu lệnh điều khiển trong Twig được sử dụng trong cặp dấu {% … %}.

<h1>Members</h1>
<ul>
    {% for user in users %}
        <li>{{ user.username|e }}</li>
    {% endfor %}
</ul>
{% if users|length > 0 %}
    <ul>
        {% for user in users %}
            <li>{{ user.username|e }}</li>
        {% endfor %}
    </ul>
{% endif %}

Comment

Tất nhiên là mỗi dòng code chúng ta viết nên có ghi chú để có thể mai kia có thể hiểu được mình đã từng viết gì.

{# note: disabled template because we no longer use this
    {% for user in users %}
        ...
    {% endfor %}
#}

Macros

Macro có thể được so sánh với functions trong các ngôn ngữ lập trình, nó được dùng để tái sử dụng các đoạn HTML mà tránh sự lặp lại không đáng có. Một macro được định nghĩa qua macro tag.

Ví dụ đơn giản về macro

{% macro input(name, value, type, size) %}
    <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}

Chúng ta cũng có thể thiết lập các giá trị mặc định của tham số trong macro

{% macro input(name, value = "", type = "text", size = 20) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
{% endmacro %}

Để sử dụng Macro thì chỉ cần import vào là xong

{% import "forms.html" as forms %}

<p>{{ forms.input('username') }}</p>

Bạn cũng có thể đổi tên cho macro đó khi import

{% from 'forms.html' import input as input_field %}

<dl>
    <dt>Username</dt>
    <dd>{{ input_field('username') }}</dd>
    <dt>Password</dt>
    <dd>{{ input_field('password', '', 'password') }}</dd>
</dl>

Expressions

Twig cho phép sử dụng expressions ở bất kì chỗ nào. Nó rất giống với PHP và nếu bạn không biết gì về PHP, bạn vẫn có thể dễ dàng sử dụng nó.

{% set greeting = 'Hello ' %}
{% set name = 'Fabien' %}

{{ greeting ~ name|lower }}   {# Hello fabien #}

{# use parenthesis to change precedence #}
{{ (greeting ~ name)|lower }} {# hello fabien #}

Mảng và đối tượng cũng có thể lồng vào nhau

{% set foo = [1, {"foo": "bar"}] %}

Biểu thức toán học : +, -, /, %, //, *, **

Biểu thức logic : and, or, not, (expr)

Bạn cũng có thể kiểm tra một chuỗi bắt đầu hoặc kết thúc bằng một chuỗi con nào đó.

{% if 'Fabien' starts with 'F' %}
{% endif %}

{% if 'Fabien' ends with 'n' %}
{% endif %}

Hoặc sử dụng biểu thức chính quy để đơn giản hóa

{% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}

Toán tử Containment sẽ trả về true nếu toán hạng bên trái nằm trong đối tượng bên phải

{# returns true #}

{{ 1 in [1, 2, 3] }}

{{ 'cd' in 'abcde' }}

Toán tử Test có thể sử dụng như một sự kiểm tra các biến

{% if post.status is not constant('Post::PUBLISHED') %}

{# is equivalent to #}
{% if not (post.status is constant('Post::PUBLISHED')) %}

Và có một vài toán tử khác, ví dụ như

{{ foo ? 'yes' : 'no' }}

{# as of Twig 1.12.0 #}
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}

Template

Nếu đã dùng Blade của Laravel thì bạn sẽ không lạ gì với các chức năng này. Twig hỗ trợ include các template khác

{{ include('sections/articles/sidebar.html') }}

Sẽ đơn giản hơn nếu bạn kế thừa các template khác khi phát triển sản phầm

<!DOCTYPE html>
<html>
    <head>
        {% block head %}
            <link rel="stylesheet" href="style.css" />
            <title>{% block title %}{% endblock %} - My Webpage</title>
        {% endblock %}
    </head>
    <body>
        <div id="content">{% block content %}{% endblock %}</div>
        <div id="footer">
            {% block footer %}
                © Copyright 2011 by <a href="http://domain.invalid/">you</a>.
            {% endblock %}
        </div>
    </body>
</html>

Có thể sử dụng lại nội dung từ các template cha nếu có nhu cầu.

{% block sidebar %}
    <h3>Table
    Of Contents</h3>
    ...
    {{ parent() }}
{% endblock %}

Twig cũng chỉ là một sản phẩm và tất nhiên sẽ có cả ưu và nhược điểm. Tuy nhiên chúng ta vẫn nên sử dụng để đơn giản hóa công việc khi phải thao tác với template. Và nếu có thể thì hãy đóng góp để Twig ngày một hoàn thiện hơn.

Tài liệu tham khảo

https://twig.symfony.com/

http://twig.sensiolabs.org/documentation