Routing trong ZF

Khi người dùng truy cập đến website bằng cách nhập URL vào trình duyệt. HTTP Request ứng dụng nhận được sẽ phân tích URL này và dẫn đến thi hành một action trong controller. Việc phân tích URL như dẫn đến gọi action tương ứng như vậy là quá trình routing (định tuyển). Trong ZF đảm trách việc này là thư viện Zend\Router

Phần này chỉ nói về Routing cơ bản ứng dụng trong Skeleton của ZF, còn chi tiết nâng cao sau này hãy đọc Router trong ZF

Cấu trúc URL

Một URL nhận được từ HTTP Resquest có một số thành phần: scheme, hostname, path, fragment, query

Ví dụ:

http://site.yourdomain.com/path/to/page/#section?a=1&b=price

Vậy URL bắt đầu bởi scheme với các giá trị như http://, https://. Theo sau là hostname như www.yourdomain.com, google.com. Có thể có path đường dẫn tới trang theo dạng cấu trúc thư mục, cách thành phần cách nhau bởi / như product/category/cate1. Nếu có fragment thì nó bắt đầu bởi ký tự #, nó biểu diễn điểm bắt đầu của một nội dung nào đó trong trang (mặc định trình duyệt sẽ cuộn trang tới fragment). Chuỗi query nếu có nó bắt đầu bới ? tiếp theo là các cặp name=value cách nhau bởi &

Các ký tự đặc biệt trong các thành phần path, fragment, query của URL phải được encode, ví dụ % trên URL sẽ là %20. Trong PHP có hàm urlencode giúp bạn encode. Đồng thời cũng có urldecode giúp bạn decode chuỗi URL.

Các kiểu Route trong ZF

Một Route khi nhận thông tin URL từ HTTP Request sẽ phân tích nó và trả lời rằng URL có phù hợp với nó hay không. Khi ứng dụng nhận thấy URL phù hợp với Route nào, thì dựa theo cấu hình mà tiến hành khởi tạo Controller phù hợp cũng như gọi action.

Dựa theo cách mà Route phân tích, ZF chia ra mấy loại sau:

Route Chi tiết
Literal Các phần của URL chính xác với các phần của Route
Segment So sánh các phân đoạn đường dẫn của URL
Regex Só sánh đường dẫn URL với một biểu thức chính quy mẫu
Hostname Kiểm tra phù họp của host với một số mẫu so sánh
Scheme Kiểm tra scheme có phù hợp có phù hợp với Route
Method Kiểm tra phương thức sử dụng HTTP Resquest có phù hợp với quy định của Route (GET, POST)

Skeleton ZF ứng dụng Route như thế nào?

Các kiểu Route ở trên, được dùng để tạo ra các route trong ứng dụng. Skeleton sẽ tập hợp các route bạn cấu hình lại trong một đối tượng Zend\Router\Http\TreeRouteStack.

Khi cho TreeRouteStack phân tích HTTP Resquest gửi đến (->match($request)), nó sẽ trả về một đối tượng RouteMatch (Zend\Router\Http\RouteMatch) nếu có Route phù hợp hoặc null nếu HTTP Request không phù hợp với một Route nào chứa trong TreeRouteStack (dẫn tới lỗi 404).

Với Skeleton trong tiến trình hoạt động của nó, có giai đoạn nó sẽ lấy RouteMatch, căn cứ thông tin trong RouteMatch mà Skeleton biết sẽ với khởi tạo Controller nào ... Vì RouteMath chứa các tham số mô tả bởi Route, lấy tham số này bằng $RouteMath->getParam('paramname')

Nếu có nhu cầu lấy RouteMatch trong ứng dụng có thể làm như sau:

//$servicemanager đã có

$router =  $servicemanager->get('router');
$request = $servicemanager->get('request');
$routeMatch = $router->match($request);

//VD - Lấy tên Controller đáp ứng lại URL
echo $routeMatch->getParam('controller');

Trong ứng dụng Skeleton, các Route được khai báo, cấu hình ... ở trong file module.config.php, ở mục routes của phần tử router

Bạn có thể mở file: module/Application/config/module.config.php kiểm tra

return [
    //...
    'router' => [
        'routes' => [
            'home' => [
                'type' => Literal::class,
                'options' => [
                    'route'    => '/',
                    'defaults' => [
                        'controller' => Controller\IndexController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
            'application' => [
                'type'    => Segment::class,
                'options' => [
                    'route'    => '/application[/:action]',
                    'defaults' => [
                        'controller' => Controller\IndexController::class,
                        'action'     => 'index',
                    ],
                ],
               ],


        ],
    //...
    ],

Như trên bạn thấy khai báo hai route có tên là homeapplication

Sử dụng Route - Literal

Đây là loại Route so sánh tên chính xác tuyệt đối, cụ thể

Cú pháp khai báo để có được Route này trong module.config.php như sau:

'nameroute' => [
        'type' => Literal::class,
        'options' => [
            'route'    => 'url-address',
            'defaults' => [
                'controller' => 'NameController',
                'action'     => ''nameaction'',
            ],
        ],
    ],
  • nameroute tên route do bạn tự đặt, chọn một cái tên không trùng với tên route khác như 'home', 'about', 'contact' ...
  • Literal::class cho biết đây là route kiểu Literal, nhớ có nạp (use Zend\Router\Http\Literal)
  • NameController tên controller mà route này biểu diễn, tên này là tên controller đã đăng ký trong hệ thống (Đăng ký Controller) như: Controller\IndexController::class, Controller\DownloadController::class ...
  • nameaction tên của action trong controller phù hợp với Route này, ví dụ index, about ...

Ví dụ: Khai báo route có tên routegioithieu để khi gõ địa chỉ là http://localhost/gioithieu.html thì sẽ gọi action có tên about của controller có tên đăng ký MyModule/CommonController

'routegioithieu' => [
        'type' => Literal::class,
        'options' => [
            'route'    => '/gioithieu.html',
            'defaults' => [
                'controller' => MyModule/CommonController::class,
                'action'     => ''about'',
            ],
        ],
    ],

Sử dụng Route - Segment

Route này so sánh sự tương ứng các thành phần trong path URL với mô tả của Route.

Cú pháp khai báo cấu hình

'nameroute' => [
        'type' => Segment::class,
        'options' => [
            'route'    => '$routestring',
            constraints => [
                //...các ràng buộc của các phần trong $routestring
            ],
            'defaults' => [
                'controller'    => 'NameController',
                'action'        => 'nameaction',
                //..các tham số tự thêm
                'abc'           => 'valueabc',
            ],
        ],
    ],

Trong đó:

nameaction tên action mặc định phù hợp và sẽ gọi bởi MVC, action này có thể thay đổi theo định nghĩa biến :action trong $routestring

NameController tên contrller đã đăng ký (xem ở trên). Trong mục defaults còn có thể tự thêm các tham số riêng, mà bạn sẽ đọc được bằng $RouteMatch->getParam('paramname')

$routestring chuỗi biểu diễn path (xem path trong cấu trúc URL ở trên) URL, nó có thể chứa các thành phần cố định và các biến. Có một số lưu ý sau:

Xét $routestring => '/product/[/:category/:id/].html'

  • $routestring biểu diễn bởi các hằng số và các biến. Nếu là biến thì có cấu trúc :varname, như trên product, .html là các hằng số. category, id là tên biến. Nếu là biến sau này giá trị thực có thể đọc được từ ->params()->fromRoute(varname) xem phần Đọc Params
  • Các thành phần có thể có hoặc không có vẫn phù hợp với Route thì chứa trong cặp ngoặc vuông [ ... ]. Như trên đó là [/:category/:id/] nghĩa là URL phù hợp phải có category và id hoặc không có cả hai.
  • Trong chuỗi nếu có biến có tên action (:action) thì nó là action sẽ thay thể giá trị mặc định nameaction. Ví dụ '/application[/:action]' nếu URL nhập vào là /application là phù hợp Route và action gọi là action trong mặc định. Nếu nhập vào là /application/showname thì vẫn phù hợp Route nhưng action gọi sẽ là showname
  • constraints là khu vực bạn khai báo các ràng buộc phải tuôn theo của biến nếu có. Các phần tử có ràng buộc thêm vào bằng cú pháp namevar => "biểu-thức-chính-quy". Bạn đọc về Biểu thức chính quy RegEx để biết cấu trúc của nó. Ví dụ như:
    • 'abc\d{2}' biến phải bắt đầu bởi abc, theo sau hai chữ số.
    • [a-zA-Z][a-zA-Z0-9_-]+ biến phải bắt đầu bằng các ký tự từ a-Z, sau đó là nhóm các ký tự a-Z, 0-9 và có thể có -

Sử dụng Regex Route

Loại Route này sử dụng biểu thức chính quy: Biểu thức chính quy RegEx để kiểm tra sự phù hợp URL với Route

'nameroute' => [
        'type' => Regex::class,
        'options' => [
            'regex'    => 'biểu - thức - chính - quy',
            'defaults' => [
                'controller'    => 'NameController',
                'action'        => 'nameaction',
                //..các tham số tự thêm
                'abc'           => 'valueabc',
            ],
        ],
    ],

Ví dụ:

'doc' => [
    'type' => Regex::class,
    'options' => [
    //page là tên biến nhận giá trị RegEx phía sau
    'regex'    => '/doc(?<page>\/[a-zA-Z0-9_\-]+)\.html',
    'defaults' => [
        'controller' => Controller\IndexController::class,
        'action'     => 'doc',
    ],
    //biểu thức để phát sinh URL
    'spec'=>'/doc/%page%.html'
    ],
    ],

Route trên phù hợp với các URL dạng /doc/<page_name>.html

Đăng ký theo dõi ủng hộ kênh