Tìm hiểu file khởi chạy ứng dụng
Zend Framework như ứng dụng Skeleton bạn ở phần trước, khởi chạy bắt đầu từ script file: index.php
trong thư mục public
Script này đơn giản, nhỏ với code ban đầu như sau:
<?php use Zend\Mvc\Application; use Zend\Stdlib\ArrayUtils; /** * This makes our life easier when dealing with paths. Everything is relative * to the application root now. */ chdir(dirname(__DIR__)); // Decline static file requests back to the PHP built-in webserver if (php_sapi_name() === 'cli-server') { $path = realpath(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)); if (__FILE__ !== $path && is_file($path)) { return false; } unset($path); } // Composer autoloading include __DIR__ . '/../vendor/autoload.php'; if (! class_exists(Application::class)) { throw new RuntimeException( "Unable to load application.\n" . "- Type `composer install` if you are developing locally.\n" . "- Type `vagrant ssh -c 'composer install'` if you are using Vagrant.\n" . "- Type `docker-compose run zf composer install` if you are using Docker.\n" ); } // Retrieve configuration $appConfig = require __DIR__ . '/../config/application.config.php'; if (file_exists(__DIR__ . '/../config/development.config.php')) { $appConfig = ArrayUtils::merge($appConfig, require __DIR__ . '/../config/development.config.php'); } // Run the application! Application::init($appConfig)->run();
Mọi yêu cầu gửi đến ứng dụng, đều kích hoạt ứng dụng bằng việc bắt đầu chạy file này, trong đó
chdir(dirname(__DIR__));
Mã trên thiết lập thư mục hiện tại ứng dụng làm việc về thư mục gốc của dự án (zf3), thư mục làm điểm gốc để xác định đường dẫn tương đối đến các thư mục, file khác trong hệ thống.
Trong phần trước có hướng dẫn mẹo nhỏ di chuyển index.php
ra thư mục gốc do vậy mặc định thư mục ứng dụng làm việc trùng với thư mục index.php
nên dòng code này được bỏ đi.
include __DIR__ . '/../vendor/autoload.php';
Dòng mã trên nạp các thư viện và module ứng dụng
Application::init($appConfig)->run();
Mã trên tạo ra một lớp Application
của Zend Framework, lớp này sử dụng các thông số cấu hình đọc được từ file application.config.php
ở thư mục config
,
sau đó khởi chạy ứng dụng
Các sự kiện chính trong Zend Framework (Skeleton)
Ở phần trước, chúng ta thấy với mỗi yêu cầu gửi tới ứng dụng một đối tượng Zend\Mvc\Application
được tạo ra, và ứng dụng bắt đầu hoạt động tồn tại trong một khoảng thời gian cho đến khi trả về
một HTTP response. Sự tồn tại này này là một vòng đời của ứng dụng, thường có một số tình huống xảy ra trong vòng đời ứng dụng Zend Framework
Vì Zend Framework 3 có khái niệm lập trình theo sự kiện. Một lớp phát đi một sự kiện, các lớp khác nghe thấy sự kiện và kích hoạt
các hàm callback. Việc quản lý sự kiện do lớp Zend\EventManager
phụ trách, Sketon có tạo mặc định lớp này trong cấu trúc của nó, ta sẽ tìm hiểu sau.
Mỗi giai đoạn trong vòng đời, ứng dụng sẽ phát đi một sự kiện (các sự kiện định nghĩa bằng lớp Zend\Mvc\MvcEvent
), và các lớp khác có thể bắt được sự kiện và đáp ứng lại yêu cầu bằng cách thi hành các tác vụ phù hợp.
Trong Zend Framework có 5 sự kiện chính:
1) bootstrap (MvcEvent::EVENT_BOOTSTRAP) : Sự kiện này do ứng dụng phát đi trước nhất khi bắt đầu khởi tạo,
các module bạn xây dựng sẽ có cơ hội khởi tạo các tham số, cấu hình bằng cách bắt sự kiện này bằng phương thức onBootstrap()
trong Module.php
.
2) route (MvcEvent::EVENT_ROUTE) : sự kiện này phát ra khi ứng dụng phân tích xong URL (lớp Zend\Router\Http\TreeRouteStack) gửi đến ứng dụng. Nếu tìm thấy sự phụ hợp của URL với hệ thống Route (điều hướng) của ứng dụng, yêu cầu sẽ chuyển đến cho Controller phù hợp để thi hành (học sau).
3) dispatche (MvcEvent::EVENT_DISPATCH) : Sự kiện phát ra khi Controller thi hành xong theo yêu cầu gửi đến, nó trả về dữ liệu để có thể hiện thị trên trang
4) render (MvcEvent::EVENT_RENDER) : sự kiện phát ra bởi Controller cho biết Controller sử dụng Zend\View\Renderer\PhpRendere
để dựng mã HTML chẳng hạn.
Các lớp có chức năng render sử dụng các file mẫu để xuất ra HTML.
5) finish (MvcEvent::EVENT_FINISH) : khi kiện xảy ra khi HTTP response được gửi cho client
Như vậy các sự kiện có thể xảy ra theo sơ đồ
Thử bắt các sự kiện của Zend Framework Skeleton
Ví dụ sau để bạn tìm hiểu qua về các sự kiện, bắt sự kiện cơ bản nhất chưa đi sâu. Như trên đã nói, khi sự kiện bootstrap xảy ra (khi ứng dụng bắt đầu khởi tạo), các module ứng dụng của bạn có thể bắt được sự kiện này
nếu lớp Module của ứng có phương thức onBootstrap(MvcEvent $e)
Giờ bạn mở file Module.php trong module Application
của ứng dụng khung (đã cài đặt ở phần Ứng dụng khung Zend Framework)
Cho thêm phương thức onBootstrap
vào lớp Module
với nội dung như sau:
public function onBootstrap(\Zend\Mvc\MvcEvent $e) { echo "Bắt được sự kiện Bootstrap<br>"; }
Giờ khi ứng dụng phát ra sự kiện
bootstrap, moduleApplication
sẽ bắt được (các module khác cũng có thể bắt được nếu có hàm này). Bạn chạy thử lại ứng dụng sẽ thấy có dòng
"Bắt được sự kiện Bootstrap"
Bên trong onBootstrap bạn cũng có thể khai báo, để bắt các sự kiện khác. Bằng cách sau: lấy đối tượng EventManager của ứng dụng (đối tượng quản lý hệ thống sự kiện),
gắn vào đó một Listener (một hàm callback gọi khi sự kiện xảy ra) lắng nghe sự kiện cụ thể) bằng phương thức attach
theo cú pháp:
$eventmanager->attach('tên-sụ-kện', listener);
Trong đó để tạo ra các listener (callback) khác nhau bạn sẽ tìm hiểu sau. Ở đây sử dụng đơn giản là khai báo luôn một Listener dạng hàm closure
dạng funtion ($e) { ... }
Ví dụ để nghe sư kiện route
khi đã có $eventmanager
$eventmanager->attach('route', function($e) { //...code chạy khi nhận sự kiện });
Tổng hợp lại, bắt các sự kiện ở trên trong hàm onBootstrap
public function onBootstrap(\Zend\Mvc\MvcEvent $e) { echo "Bắt được sự kiện Bootstrap lúc ".microtime (true).". <br>"; //Lấy bộ quản lý Event Manager $eventmanager = $e->getApplication()->getEventManager(); //Khai báo lắng nghe sự kiện 'finish' $eventmanager->attach('finish', function($e) { echo "finish: nhận được lúc vào lúc - ".microtime (true)."<br>"; }); //Khai báo lắng nghe sự kiện 'route' $eventmanager->attach('route', function($e) { echo "route: nhận được lúc vào lúc - ".microtime (true)."<br>"; }); //Khai báo lắng nghe sự kiện 'dispatch' $eventmanager->attach('dispatch', function($e) { echo "dispatch: nhận được lúc vào lúc - ".microtime (true)."<br>"; }); //Khai báo lắng nghe sự kiện 'render' $eventmanager->attach('finish', function($e) { echo "finish: nhận được lúc vào lúc - ".microtime (true)."<br>"; }); }
Bạn hãy chạy thử để xem các sự kiện diễn ra