+3

Statamic - Một CMS tốt xây dựng trên Laravel

Tổng quan

Ở bài viết này chúng ta sẽ tìm hiểu những thông tin về một CMS được xây dựng trên Laravel là Statamic. Bài viết sẽ cung cấp những thông tin cơ bản nghiên cứu của mình về Statamic sau khi áp dụng nó vào dự án công nghệ. Mong thong qua bài viết sẽ cung cấp cho mọi người thông tin để có thêm sự lựa chọn cho dự án của bản thân.

Giới thiệu về Statamic

  • Statamic là một CMS (Content Management System) được xây dựng trên framework nổi tiếng Laravel. Nó cung cấp đầy đủ các chức năng của một CMS cần có
  • Statamic có sự tùy biến linh hoạt dựa trên yêu cầu của dự án. Nó có thể là một full-stack CMS, một headless CMS hoặc là một static file generator. Statamic có thể lưu trữ dữ liệu dựa trên flat file hoặc là database rất linh hoạt.
  • Statamic khẳng định sự linh hoạt của mình như sau:
  • Ngoài ra Statamic cũng cung cấp khả năng mở rộng chức năng linh hoạt dựa trên cửa hàng Addons của mình và cũng cung cấp khả năng để chúng ta có thể tự viết Addons dựa trên nhu cầu của mình
  • Về chi phí:
    • Statamic cung cấp bản Free giới hạn một vài tính năng
    • Statamic cung cấp bản Pro miễn phí trên môi trường develop ở local để chúng ta dễ dàng xây dựng và phát triển website. Và để deploy một website với Statamic bản Pro sẽ cần phải trả 275$ / 1 site
    • Xem thêm thông tin ở link

Những ưu điểm và nhược điểm của Statamic

Ưu điểm

  • Hỗ trợ kết hợp tốt với các dự án dùng framework Laravel, một framework cho PHP được sử dụng nhiều nhất hiện nay
  • Vì được xây dựng trên nền tảng của Laravel nên dễ dàng tiếp cận và dễ dàng phát triển các chức năng mở rộng
  • Giao diện sử dụng trực quan, dễ dùng dành cho người quản trị website
  • Có cung cấp documentation cho developer

Nhược điểm

  • Template engine được khuyến nghị sử dụng và hỗ trợ chính là Antler, đây là một template engine theo đánh giá cá nhân mình là khá hay khi sử dụng nhưng tài liệu được statamic cung cấp cũng như trên mạng khá hạn chế nên sẽ cần nhiều thời gian để nghiên cứu và sử dụng. Tuy nhiên bên cạnh đó thì Statamic hỗ trợ cả Blade nên mọi người có thể lựa chọn template engine phù hợp cho dự án và team của mình
  • Documentation với lượng thông tin đầy đủ, tổng quát tuy nhiên chưa sâu, dẫn đến việc gặp một vấn đề chuyên sâu thì không tìm thấy được tài liệu cần thiết, ngoài ra nguồn tài liệu liên quan về Statamic trên internet cũng khá ít và cộng đồng hỗ trợ chưa quá nhiều

Các khái niệm cốt lõi

Entry & Collections

  • Entry: là khái niệm chỉ đến một entity lưu trữ data của statamic. Để hiểu đơn giản thì nó là thông tin của 1 bài blog, 1 sản phẩm, ... tùy theo bạn định nghĩa
  • Collections: Là một tập hợp các entries và cũng là nơi quản lý các entries. Khi sử dụng CMS Statamic thì chúng ta sẽ tạo một Collection để định nghĩa thông tin nhóm đối tượng mà chúng ta muốn lưu trữ và tác động
  • Lưu ý việc đặt tên cho Collections là rất quan trọng vì tên của Collections sẽ quyết định URL để lấy data của collections đó, URL của API cho collections đó, cách lấy data của collection từ Antler.
  • Để định nghĩa các trường thông tin có thể lưu ở các Entries của Collections thì sẽ cần định nghĩa các Field ở Blueprints - khái niệm mà mình sẽ đề cập ở bên dưới
  • Mặc định data của Collections và Entries sẽ được Statamic lưu trữ ở dạng file YAML. Để chuyển qua sử dụng Database thì mình sẽ giới thiệu cách làm ở mục bên dưới

Blueprints

  • Có thể hiểu Blueprints đúng với tên của nó: một bản thiết kế để xây dựng nên các Entries của Collections.
  • Ở Blueprints chúng ta sẽ định nghĩa đầy đủ các Field và kiểu dữ liệu cũng như quy tắc validation cho các dữ liệu đó
  • Việc thiết kế Blueprints phù hợp với yêu cầu bussiness của dự án là rất quan trọng. Việc thiết kế cấu trúc dữ liệu đúng sẽ giúp chúng ta đỡ tốn thời gian để fix những lỗi phát sinh.
  • Bên cạnh đó Statamic cũng cung cấp khả năng cập nhật và mở rộng Blueprints một cách đơn giản, tuy nhiên khi thay đổi, cập nhật Blueprint của một Collection thì chúng ta cần chú ý xử lý những ảnh hưởng mà thay đổi đó có thể gây ra

Field

  • Là những dòng thông tin mà chúng ta phải nhập để tạo một Entry và được quy định bởi Blueprints của Entry đó
  • Field sẽ quy định label, tên trường và kiểu dữ liệu được lưu cho trường đó
  • Statamic cung cấp rất nhiều kiểu Field có sẵn để lựa chọn (Fieldtypes)
  • Lưu ý có những fieldtype sẽ quy định mối quan hệ của entry với những entry khác

Navigation

  • Statamic cung cấp một cấu trúc xử lý việc lưu trữ các giá trị trang điều hướng cần có cho mọi trang web
  • Với chức năng này, chúng ta có thể tạo ra các items về điều hướng và sắp xếp thứ bậc, mối quan hệ cha - con giữa chúng
  • Navigation cũng sở hữu Blueprint và chúng ta có thể chỉnh sửa tùy ý để quy định các data có thể lưu trữ cho từng items

Taxonomies

  • Là một hệ thống phân loại được Statamic cung cấp để phân loại dữ liệu dựa trên một đặc điểm mà chúng ta quy định. Để dễ hình dung thì nó chính là phân loại theo tags hay theo categories thường thấy trên các website
  • Taxonomies là phương thức chính để nhóm lại các nội dung theo một chủ đề hoặc một thuộc tính chung
  • Taxonomies cũng có Blueprint riêng để chúng ta dễ dành quy định cấu trúc thông tin của các Taxonomies
  • Statamic cũng hỗ trợ chúng ta có thể truy cập trực tiếp Taxonomies từ Views

Assets

  • Như các CMS khác thì Statamic cũng cung cấp một hệ thống quản lý file để chúng ta có thể upload và quản lý các file ảnh, video, tài liệu,... cần thiết cho website
  • Chúng ta có thể quy định nơi lưu trữ của các assets là ở trực tiếp trên server, ở AWS S3 hoặc ở các dịch vụ lưu trữ file khác mà Statamic hỗ trợ
  • Statamic cung cấp một hệ thống quản lý file trực quan, dễ sử dụng và dễ dàng tiếp cận cho người quản trị hệ thống
  • Việc truy cập vào các Assets cũng rất đơn giản vì Statamic đã hỗ trợ sẵn cách truy cập ở Front-end thông qua Template Engine hoặc API

Users

  • Statamic cung cấp một hệ thống quản lý người dùng trên website với đầy đủ các tính năng như phân roles và permissions (lưu ý để có đầy đủ các tính năng này thì cần phải có bản Pro)
  • Users cũng có Blueprint để chúng ta có thể tùy chỉnh các thông tin cần lưu của user
  • Việc truy cập thông tin của các user cũng được Statamic hỗ trợ tốt và chúng ta có thể dễ dàng truy cập dữ liệu từ Front-end thông qua một vài biến đơn giản

Các khái niệm liên quan tới lập trình

Routing

  • Statamic cung cấp nhiều cách định nghĩa các routes cho hệ thống
  • Mặc định, các routes sẽ được xử lý bởi Statamic routes
  • Statamic cung cấp phương thức Route::statamic() để định nghĩa route theo mặc định. Với Statamic route chúng ta có thể đưa data vào view, xử lý layout, view, ...
Route::statamic('uri', 'view', ['foo' => 'bar']);
{{ myglobal }} // Biến global

{{ foo }} // bar
  • Có thể truyền một hàm để xử lý dữ liệu trước khi truyền qua view
Route::statamic('uri', 'view', function () {
    $bar = gatherDataExpensively();
 
    return ['foo' => $bar];
});
  • Định nghĩa parameter cho route
Route::statamic('things/{thing}', 'things.show');
{{ thing }}
  • Ngoài ra còn có thể quy định layout cho view
Route::statamic('uri', 'view', ['layout' => 'custom']);
  • Ngoài Statamic Routes thì Statamic cũng hỗ trợ định nghĩa routes theo kiểu thông thường của Laravel hay có thể gọi đơn giản là Laravel Routes
use Illuminate\Support\Facades\Route;
 
Route::get('/greeting', function () {
    return 'Hello World';
});
  • Lưu ý: Nếu sử dụng chức năng Static Cache thì cần phải sử dụng thêm Middleware Caching khi định nghĩa Laravel Routes
Route::get('/thingy', function () {
    // ...
})->middleware(\Statamic\StaticCaching\Middleware\Cache::class);
  • Nếu như hoàn toàn không cần dùng Statamic Routes thì có thể disable nó đi và chỉ sử dụng Laravel Routes bằng cách chỉnh sửa config ở config/statamic/routes.php
'enabled' => false,

Controller

  • Statamic hỗ trợ cách định nghĩa Controller y hệt như Laravel. Tất cả các tính năng của Controller mà Laravel cung cấp thì Statamic đều có thể sử dụng
<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
 
class ExampleController extends Controller
{
    public function index()
    {
        $data = [
            'title' => 'Example Title'
        ];
 
        return view('myview', $data); // resources/views/myview.blade.php
    }
}
  • Ngoài ra trong controller còn có thể sử dụng thêm các chức năng của Statamic như trả về một Statamic View
public function index()
{
    return (new \Statamic\View\View)
        ->template('myview')
        ->layout('mylayout')
        ->with(['title' => 'Example Title']);
}

View & Antlers

  • Như đã để cập lúc giới thiệu tổng quan, Statamic sử dựng Antlers để làm template engine mặc định cho hệ thống của mình
  • Antlers có cú pháp và cách sử dụng khá hay và cũng cung cấp đầy đủ các chức năng không thua kém gì Blade. Sau đây chúng ta sẽ đi sâu tìm hiểu về nó

Basic Syntax

  • Để sử dụng biến trong Antlers thì sử dụng syntax: {{ variable ]}
  • Để gọi câu lệnh PHP thì sử dụng syntax: {{? ?}} hoặc {{$ $}}
  • Để command: {{# #}}

Kiểu dữ liệu dạng mảng và vòng lặp

  • Với kiểu dữ liệu dạng mảng thì chúng ta có thể lặp qua và hiển thị dữ liệu đơn giản như sau
<ul>
{{ songs }}
  <li>{{ value }}</li>
{{ /songs }}
</ul>
  • Khi ở trong vòng lặp thì Antlers hỗ trợ 2 biến đặc biệt là nextprev
<ul>
{{ songs }}
  <li>{{ value }} (Next: {{ next:value }}) (Prev: {{ prev:value }})</li>
{{ /songs }}
</ul>
  • Ngoài ra Antlers cũng cung cấp cách truy cập dựa trên index
<p>Let's go {{ sports:0 }}, {{ sports.1 }} or {{ sports[2] }}.</p>

Modifiers

  • Modifiers giúp thay đổi output hiển thị theo mong muốn
<!-- $title = 'Nickelodeon Studios' -->
<!-- NICKELODEON STUDIOS rocks! -->
<h1>{{ title | upper | ensure_right('rocks!') }}</h1>
 
<!-- NICKELODEON STUDIOS ROCKS! (kết quả sẽ theo thứ tự modifiers) -->
<h1>{{ title | ensure_right('rocks!') | upper }}</h1>
  • Statamic cung cấp 150 modifiers được xây dựng sẵn. Có thể xem danh sách các modifiers ở đây: link
  • Ngoài ra chúng ta cũng có thể tự xây dựng modifiers riêng theo chúng ta tự định nghĩa

Condition

  • Antlers cung cấp syntax cho câu lệnh điều kiện cơ bản
<title>
  {{ if meta_title }}
    {{ meta_title }}
  {{ elseif title }}
    {{ title }}
  {{ else }}
    {{ site:name }}
  {{ /if }}
</title>
  • Với unless
{{ unless logged_in }}
  You see a large wardrobe in front of you.
{{ /unless }}
  • Với switch
{{ size = 'lg' }}
 
{{ switch(
        (size == 'sm') => '(min-width: 768px) 35vw, 90vw',
        (size == 'md') => '(min-width: 768px) 55vw, 90vw',
        (size == 'lg') => '(min-width: 768px) 75vw, 90vw',
        (size == 'xl') => '90vw',
        () => '100vw'
    )
}}

Tags

  • Là những method chính được Statamic xây dựng để truy cập dữ liệu từ Antlers và khai thác nhiều tính năng có sẵn như search, form, nav, pagination, filter, image resize, ...
<!-- Ví dụ để truy cập tất cả các entries từ collection blog -->
<ul>
  {{ collection:blog }}
    <li><a href="{{ url }}">{{ title }}</a>
  {{ /collection:blog }}
</li>
  • Danh sách các Tags có thể xem được ở đây: link

Layout

  • Layout là một thuật ngữ không còn quá xa lạ trong việc xây dựng Front-end. Antlers cung cấp cách sử dụng layout tùy biến và hoàn thiện
  • Để định nghĩa Layout cho trang thì chúng ta tạo một antlers file như trang view bình thường (mặc định khi mới cài project Statamic thì sẽ có file layout.antlers.html) và sau đó chỉ định file đó là layout cho trang khác ở trong Admin hoặc trong code
<!-- layout.antlers.html -->
<!doctype html>
<html lang="{{ site:short_locale }}">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{{ title ?? site:name }}</title>
        {{ vite src="resources/js/site.js|resources/css/site.css" }}
    </head>
    <body class="bg-gray-100 font-sans leading-normal text-gray-800">
        <div class="mx-auto px-2 lg:min-h-screen flex flex-col items-center justify-center">
            {{ template_content }}
        </div>
    </body>
</html>

Partials

  • Để chia view thành các phần (component) để có thể tái sử dụng code thì Antlers cung cấp chức năng chia các view thành các Partials và có thể sử dụng các Partials đó để nhúng vào view khác
{{# Nhúng partial ở đường dẫn resources/views/partials/footer.antlers.html #}}

{{ partial:footer }}
  • Chúng ta có thể truyền biến vào trong partial để tiếp tục xử lý
{{ partial:blog/card mode="stacked" }}
  • Khi sử dụng Partial thì sẽ có các trường hợp chúng ta muốn truyền nội dung hiển thị vào vị trí được định sẵn của nó. Để giải quyết yêu cầu này chúng ta có thể sử dụng slot
{{# /resources/views/partials/modal.antlers.html #}}
 
<div class="modal">
  {{ slot }}
</div>
{{ partial:modal }}
  <h2>50% off everything, today only!</h2>
  <a href="/sale">
    <img src="/img/sale.jpg" alt="Man eating banana on sale." />
  </a>
{{ /partial:modal }}

Ngoài các chức năng trên thì Antlers còn cung cấp thêm nhiều các chức năng khác có thể được tìm thấy ở documentation của Statamic hoặc ở blog chuyên viết về Antlers ở link sau: blog

REST API

  • Statamic cung cấp các API để có thể cung cấp nội dung và data cho frontend, external apps, SPAs, ...
  • Để bật chức năng này thì cần thêm ở file .env
STATAMIC_API_ENABLED=true
  • Statamic cung cấp khả năng tùy chỉnh các resource (Collections, Taxonomies, ...) nào sẽ có API ở file config config/statamic/api.php
'resources' => [
  'collections' => true,
  'taxonomies' => true,
  // etc
]

Entries

  • Lấy data từ collections GET /api/collections/{collection}/entries
{
  "data": [
    {
      "title": "My First Day"
    }
  ],
  "links": {...},
  "meta": {...}
}
  • Lấy data từ 1 entry duy nhất GET /api/collections/{collection}/entries/{id}
{
  "data": {
    "title": "My First Day"
  }
}

Navigation Tree

GET /api/navs/{nav}/tree

{
  "data": [
    {
      "page": {
        "title": "Recommended Products",
        "url": "https://rainforest.store/?cid=statamic",
      },
      "depth": 1,
      "children": [
        {
          "page": {
            "title": "Books",
            "url": "https://rainforest.store/?cid=statamic&type=books",
          },
          "depth": 2,
          "children": []
        }
      ]
    }
  ]
}

Taxonomy Terms

GET /api/taxonomies/{taxonomy}/terms

{
  "data": [
    {
      "title": "Music",
    }
  ],
  "links": {...},
  "meta": {...}
}

Users

GET /api/users

{
  "data": [
    {
      "id": "1",
      "email": "john@smith.com",
      "api_url": "http://example.com/api/users/1"
    }
  ],
  "links": {...},
  "meta": {...}
}

Assets

GET /api/assets/{container}

{
  "data": [
    {
      "id": "main::foo.jpg",
      "url": "/assets/foo.jpg",
      "api_url": "http://example.com/api/assets/main/foo.jpg",
      "alt": "A picture of nothing."
    }
  ],
  "links": {...},
  "meta": {...}
}

Rate Limit

  • Theo mặc định Statamic sẽ để rate limit là 60 yêu cầu / 1 phút
  • Để config rate limit thì cần sửa ở file app/Providers/RouteServiceProvider.php
// app/Providers/RouteServiceProvider.php
protected function configureRateLimiting()
{
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(60);
    });
}

Cách chuyển từ lưu trữ data dạng file mặc định sang sử dụng database

  • Mặc định thì Statamic sẽ lưu trữ data của nó ở dạng file, để chuyển qua sử dụng database thì cần thêm một vài bước được mô tả ở bên dưới (Lưu ý các bước dưới đây dành cho phiên bản Statamic 4)
  • Cài đặt package
composer require statamic/eloquent-driver:3.4.1
  • Publish config file
php artisan vendor:publish --tag="statamic-eloquent-config"
  • Xóa và chỉnh sửa một vài file mặc định khi tạo mới Statamic
    • Xóa file content/collections/pages/home.md
    • Thay đổi dữ liệu ở file content/trees/collections/pages.yaml thành {}.
  • Publish migrate file
php artisan vendor:publish --provider="Statamic\Eloquent\ServiceProvider" --tag=migrations
php artisan vendor:publish --tag="statamic-eloquent-entries-table" 
php artisan vendor:publish --tag="statamic-eloquent-entries-table" 
  • Chạy câu lệnh migrate
php artisan migrate
  • Mọi người có thể tham khảo thêm chi tiết các bước ở đây hoặc link github của package sau: link
  • Ngoài ra để chuyển data của User sang database thì có thể tham khảo các bước ở đây

Caching & Static Caching

  • Để tăng tốc độ cho website thì Statamic cung cấp nhiều chế độ cache

The Stache

  • Là một kĩ thuật, chức năng của Statamic để xử lý cache data được lưu trên file, không dùng đến database
  • Statamic sẽ tập hợp các data trên file dữ liệu theo một cấu trúc hiệu quả, được đánh index và sau đó lưu trữ nó trên cache ứng dụng của Laravel
  • Không thể tắt đi chức năng này vì nó là chức năng cốt lõi của Statamic
  • Các command thường dùng với stache:
php please stache:clear
php please stache:warm
php please stache:refresh

Application Cache

  • Là nơi lưu trữ cache của website, ứng dụng, addons, Laravel packages và cả chính Statamic trong một khoảng thời gian được định nghĩa trước
  • Stache cũng được lưu trữ ở đây
  • Câu lệnh thường dùng với Application Cache
php artisan cache:clear

View Fragments

  • Có những lúc chúng ta chỉ muốn cache một phần của view trên Antlers Template để giảm thời gian tải trang. Để giải quyết vấn đề này thì Statamic cung cấp cache tag
{{ cache for="1 hour" }}
  something impressive but slow here
{{ /cache }}

Static Caching

  • Đây là cách cache cho tốc độ tải trang nhanh nhất với việc chỉ cung cấp các nội dung trang static. Tuy nhiên đánh đổi lại đó là việc xử lý các thành phần tương tác động trên website
  • Statamic sẽ lưu trữ các trang tĩnh và chuyển định tuyến sang Apache hoặc Nginx thông qua reverse proxying.
  • Chúng ta có thể sử dụng static caching cho từng trang một

Tổng kết

Trên đây là những thông tin tổng quát và những khái niệm cốt lõi nhất về Statamic. Ngoài các thông tin được cung cấp trong bài viết thì Statamic còn có rất nhiều khái niệm, tính năng hay và thú vị mà ta có thể áp dụng nhưng với tiêu chí ngắn gọn, cốt lõi thì mình sẽ không đưa hết các khái niệm đó vào bài viết. Mọi người có thể tìm hiểu thêm nếu thấy hứng thú ở các tài liệu mà mình để ở bên dưới. Mình xin cảm ơn mọi người đã đọc bài viết và hẹn gặp lại mọi người ở bài viết sắp tới.

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí