12/08/2018, 13:29

Blade template vs Twig template

I. Giới thiệu Blade Template và Twig Template Blade là template engine mặc định của Laravel Framework (kể từ Laravel 2 năm 2011). Cú pháp của Blade được lấy cảm hứng từ cú pháp ASP.NET Razor và được cải thiện để template được viết ra một cách rõ ràng hơn. Nhưng cú pháp chỉ là một phần, lợi ích ...

I. Giới thiệu Blade Template và Twig Template

Blade là template engine mặc định của Laravel Framework (kể từ Laravel 2 năm 2011). Cú pháp của Blade được lấy cảm hứng từ cú pháp ASP.NET Razor và được cải thiện để template được viết ra một cách rõ ràng hơn. Nhưng cú pháp chỉ là một phần, lợi ích chính của việc sử dụng Blade thay thế cho php thuần là giúp bạn dễ dàng sử dụng lại hoặc chia nhỏ các template

Twig được phát triển bởi Fabien Potiencer và được nằm trong gói cài đặt mặc định của Symfony2. Twig có thể sử dụng một cách độc lập và có rất nhiều project hỗ trợ Twig. Drupal 8 sử dụng Twig làm template engine. Twig cũng được cho là đã được thêm vào Laravel, nhưng cuối cùng nó đã được loại bỏ trước khi phát hành chính thức.

II. Twig vs Blade

Cả 2 đều giống nhau tại một số điểm:

  • Biên dịch ra PHP thuần
  • Hiển thị giá trị của biến một cách đơn giản
  • Có cấu trúc điều khiển
  • Escape dữ liệu
  • Template-inheritance và sections

Chúng khác nhau ở các điểm sau: cú pháp, các xử lý escape, xử lý truy cập biến, cách thêm tính năng mới và quan điểm về an ninh, dưới đây ta sẽ đi cụ thể về sự khác nhau đó:

  • Hiển thị giá trị của biến

    Hiện thị giá trị của biến có lẽ là điều phổ biến nhất trong template của bạn, vì vậy nó phải được thực hiện một cách dễ dàng. Nhưng quan trọng hơn, nó phải an toàn.

    • Blade:

      Escaped output:

		{{ $var }}
	Raw output:
		{!! $var !!}
* Twig

	Escaped output:
		{{ var }}
	Raw output:
		{{ var|raw }}
  Balde đưa cho bạn lựa chọn thay đổi thẻ trong khi đó Twig cung cấp cho bạn lựa chọn thay đổi escape mặc định. Cả 2 đểu không phải là quá thông minh trong hầu hết trường hợp, bởi vì output có thể là không được đoán định trước bởi các developer.

  Ngoài cách trên Twig còn cung cấp cho bạn tùy chọn để sử dụng các escaping methods khác nhau, ví dụ như JS hoặc thuộc tính HTML
Ví dụ
        {{ user.username|e('css') }}
        {% autoescape 'js' %}
            Everything will be automatically escaped in this block (using the JS strategy)
        {% endautoescape %}
  • Truy cập thuộc tính

    Với Twig thì điều này khá dễ dàng bằng cách sử dụng ký hiệu dấu chấm. Bạn có thể làm điều này với cả object hoặc array.

    $user->name    --> user.name
    $user['name']  --> user.name
Trong khi đó với Blade, điều này tương tụ như với PHP thuần
  • Cấu trúc điều khiển

    • Trong Blade, hầu hết các cấu trúc điều khiển chỉ đơn giản là thay thế bằng PHP tương đương của nó trong quá trình biên dịch, chi tiết bạn có thể tham khảo trong mã nguồn. Một số cấu trúc thì có hơi khác một chút, ví dụ như forelse.
        @forelse ($user in $user)
            @if(!$user->subscribed)
                {{ $user->name }}
            @endif
        @empty
            <p>No users found</p>
        @endforelse
        <?php $empty = true; foreach($user in $user): $empty = false; ?>
            <?php if (!$user->subscribed) : ?>
                <?php echo e($user->name); ?>
            <?php endif; ?>
        <?php endforeach; if ($empty): ?>
            <p>No users found</p>
        <?php endif; ?>
* Trong Twig, cấu trúc điều khiển được gọi là các thẻ, Chúng được compile bởi một Lexer và có thể phức tạp hơn một chút. Ví dụ, một thẻ lặp for được thêm loop, bạn có thể truy cập vào các trạng thái lặp hiện hành như: loop.first, loop.last, loop.index...
        {% for user in users %}
        {% if not user.subscribed %}
            {{ user.name }}
        {% endif %}
        {% else %}
            <p>No users found</p>
        {% endfor %}
  • Template inheritance và sections

    Về mặt này cả 2 tương đối giống nhau, chúng chỉ khác nhau về cú pháp. Ví dụ

    • Blade:
         
        <html>
            <head>
                <title>App Name - @yield('title')</title>
            </head>
            <body>
                @section('sidebar')
                    This is the master sidebar.
                @show
        <div class="container">
                    @yield('content')
                </div>
            </body>
        </html>
         
        @extends('layouts.master')
        @section('title', 'Page Title')
        @section('sidebar')

        <p>This is appended to the master sidebar.</p>
        @endsection
        @section('content')
            <p>This is my body content.</p>
        @endsection
* Twig:
         
        <html>
            <head>
                <title>App Name - {% block title %}{% endblock %}</title>
            </head>
            <body>
                {% block sidebar %}
                    This is the master sidebar.
                {% endblock %}

                <div class="container">
                    {% block content %}{% endblock %}
                </div>
            </body>
        </html>
         
        {% extends "layouts.master" %}
        {% block title %}Page Title{% endblock %}
        {% block sidebar %}
            {{ parent() }}
            <p>This is appended to the master sidebar.</p>
        {% endblock %}
        {% block content %}
        <p>This is my body content.</p>
        {% endblock %}
  • Bảo mật và Bối cảnh

    Như đã nói ở trên, Blade không thực sự khác PHP thuần là mấy. Nó làm việc escape dữ liệu trở lên khá đơn giản, nhưng Blade lại ko đặt ra bất cứ hạn chế nào. Twig lại khác khác, nó hoạt động dựa trên bối cảnh. Tất cả các function và filter được gọi được giới hạn bởi các chức năng rõ ràng mà bạn cho phép. Cả 2 đều có những ưu, nhược điểm riêng. Trong Twig, rất khó để bạn thực hiện một shortcut; ví dụ như: gọi một câu query trong template của bạn. Bạn sẽ phải truyền nó ra view hoặc chấp nhận truy cập đến một chức năng nhất định. Nhược điểm là đôi khi bạn phải tốn khá nhiều công sức để thực hiện một việc đơn giản. Trong Blade, bạn có thể làm như sau:

    @foreach(User::where('active')->get() as $user)
        {{ $user->name }}
    @endforeach
Điều này là bất khả thi trong Twig. Thay vào đó bạn phải truyền kết quả ra view (từ controller hoặc view composer), hoặc nếu bắt buộc phải làm thì bạn sẽ gọi 1 instance của Model User:
    {% for user in model.where('active').get() %}
      {{ user.name }}
    {% endfor %}
Twig còn cung cấp 1 chế độ sandbox, trong đó có thể tạo ra một bối cảnh an toàn, ví dụ như cho phép người dùng chỉnh sửa các template của họ với hạn chế truy cập vào hàm và biến.
  • Mở rộng chức năng

    Mở rộng directive trong Blade là khá đơn giản, nhưng lại giới hạn việc thay thế thẻ với dòng khác.

    <?php
    // @upper($var)
    Blade::directive('upper', function($expression) {
        return "<?php echo strtoupper{$expression}; ?>";
    });
Trong Twig, viết một function hoặc filter mới cũng khá đơn giản, nhưng để custom tag thì khó hơn nhiều, và thường thì bạn không cần làm điều đó. Ví dụ về 1 filter đơn giản
    <?php
    //
    $filter = new Twig_SimpleFilter('upper', function ($string) {
        return strtoupper($string);
    });
Cả 2 đều hỗ trợ marco, bạn có thể tìm đọc trong document.
  • Performance

    Blade nhanh hơn một chút vì nó đơn giản hơn nhưng cuối cùng cả Blade và Twig đều được biên dịch thành PHP thuần nên sự khác nhau về performance có thể bỏ qua.

III. Tổng kết

Cả Blade và Twig đều cung cấp các tính năng quan trọng nhất: template inheritance, sections, escaping dữ liệu và cú pháp trong sáng. Blade cung cấp cú pháp đơn giản hơn nhưng lại không có nhiều function hỗ trợ. Twig thì tiến xa hơn một chút, nó đảm bảo về mặt bảo mật và có thêm nhiều tính năng. Lựa chọn cái nào thì tùy thuộc vào sở thích của bạn. Nếu bạn chủ yếu làm việc với Laravel thì Balde sẽ là tốt hơn. Nếu bạn cùng lúc sử dụng rất nhiều framework khác thì Twig là lựa chọn phù hợp hơn.

Nếu bạn muốn sử dụng Blade trong Laravel có thể tham khảo tại đây: https://github.com/rcrowe/TwigBridge

0