Với Zend Framework 3 có một số cơ chế nạp các thư viện, các thành phần độc lập, module vào ứng dụng. Mỗi cơ chế có ảnh hưởng đến cách tổ chức thư mục trong ứng dụng.
Tự động nạp theo chuẩn PSR-4 của Zend Framework
Các thư viện, thành phần độc lập cài đặt ở thư mục vendor sẽ được ZF tự động nạp khi cần dùng đến bằng cách sử dụng khai báo namespace và tên lớp thích hợp. Để xem PSR-4 hoạt động như thế nào hãy xem lại Tiêu chuẩn PSR-4
Một trong yếu tố cốt yếu của Zend Framework là bạn phát triển ứng dụng với các module, mỗi module thực hiện một chức năng nào đó. Các module bạn xây dựng sẽ được nạp khi ứng dụng hoạt động theo nguyên lý của PSR-4
Trong ứng dụng Zend Skeleton, một module mặc định được tạo sẵn cho bạn đó là Application nằm ở thư mục module/Application, trong đó định nghĩa các lớp, các thành phần của module
Giờ bạn xem ZF nạp module đó như thế nào: Mở file composer.json bạn thấy đoạn cấu hình
"autoload": { "psr-4": { "Application\\": "module/Application/src/" } },
Đoạn code đó cho biết Composer
đã từng phát sinh code để tự động nạp module Application vào ứng dụng.
Do khai báo psr-4 là "Application\\": "module/Application/src/" có nghĩa namespace đầu tiên Application
trở vào thư mục module/Application/src/
,
và các lớp sẽ viết theo thư mục con trong src
dần dẫn đến tên lớp.
Ví dụ có lớp: Application\Controller\IndexController, có nghĩa trong src
có thư mục Controller
, và có file IndexController.php
,
bên trong định nghĩa lớp IndexController
: bạn mở thư mục ứng dụng ra kiểm tra
Áp dụng PSR-4
Giờ áp dụng, nếu bạn muốn xây dựng một module mới, giả sử module có tên MyFirstModule
và tự động nạp các thành phần của module đó theo psr-4:
(Ví dụ này sử dụng Zend Skeleton Application cài đặt theo cách của bài 1)
Bước 1) Tạo một thư mục có tên MyFirstModule
trong thư mụcmodule
Bước 2) Tạo một thư mục tên src
trong MyFirstModule
, và các thư mục con khác đến cấp thư mục con tùy thích trong src
.
Ví dụ dự định đặt một vài lớp trong thư mục Lib1
thì tạo thư mục Lib1
(giờ đường dẫn đầy đủ đến thư mục Lib1 là module/MyFirstModule/src/Lib1
Tạo lớp PHP có tên Vidupsr4, tạo ra file có tên Vidupsr4.php
trong Lib1, và mở ra cập nhật nội dung như sau
<?php //Khai báo đúng namespace: tên-module/đường-dẫn-đến-class namespace MyFirstModule\Lib1; //Tên class trùng tên file.php class Vidupsr4 { public function __construct() { echo __CLASS__.' đã được tạo'; } } ?>
Với cách tổ chức thư mục và xây dựng code như trên, đã hương tới việc gọi ra được lớp Vidupsr4 bằng cách viết: MyFirstModule\Lib1\Vidupsr4
Bước 3 cập nhật autoload
Để khai báo tự động nạp theo đúng PSR-4, mở file composer.json, và thêm vào khu vực psr-4 một dòng:
"MyFirstModule\\": "module/MyFirstModule/src/"
"autoload": { "psr-4": { "Application\\": "module/Application/src/", "MyFirstModule\\": "module/MyFirstModule/src/" } },
Cuối cùng cập nhật vào autoload.php trong vendor bằng cách gõ lệnh composer tại thư mục dự án
composer dump-autoload
Ứng dụng
Từ giờ bạn có thể sử dụng 'MyFirstModule' với lớp MyFirstModule\Lib1\Vidupsr4 bất kỳ đâu.
Ví dụ: Mở file IndexController.php
của module Application
, cập nhật phương thức indexAction()
(file này Controller gọi khi gõ đường dẫn gốc vào trình duyệt, tìm hiểu sau)thành:
public function indexAction() { new \MyFirstModule\Lib1\Vidupsr4(); return new ViewModel(); }
Kiểm tra thử kết quả trên trình duyệt, có dòng: MyFirstModule\Lib1\Vidupsr4 đã được tạo, như vậy thư viện, module đã nạp chính xác
Nạp module với ModuleManager
Các nạp các module ZF với chuẩn PSR-4 ở trên được khuyến khích ở các phiên bản sau này của Zend Framework, trong ZF có thành phần quản lý các module gọi là Module Manager (tìm hiểu sau), sẽ phối hợp để cấu hình chính xác module. Ngoài cách trên Module Manager, kết hợp với Zend Loader nạp module tự động theo cách tìm tên module trong các thư mục khái báo trước. Cách này phổ biến ở các phiên bản ZF2, nhưng vẫn có thể dùng lại cùng với ZF3
Khai báo đường dẫn tới các module
Bạn mở file: config/application.config.php
, sẽ thấy có vị trí khai báo mảng chứa các đường dẫn này
'module_paths' => [ './module', './vendor', ],
Bạn thấy ứng dụng khung khai báo sẵn hai đường dẫn chứa các thư viện, module là ./module
và ./vendor
, tại đây nếu muốn bổ xung
thêm thư mục chứa module thì thêm vào.
PHP7 cho phép sử dụng thêm ký hiệu ngoặc vuông []
biểu diễn mảng, thay thế được cho array()
Tạo một module theo kiểu để ModuleManager/Loader tự động tìm tải
Ở đây là các bước thực hành cơ bản, bạn chưa cần hiểu rõ nhiều (vì còn nhiều thứ trình bày sau), mục đích chỉ là tìm hiểu cơ chế nạp module
Tạo một module có tên ModuleA
, chứa trong thư mục ./module
:
Cấu trúc file/thư mục moduleA cuối cùng sẽ như sau
ModuleA | | autoload_classmap.php | Module.php | +---config +---src | ClassA.php | \---view
Bước 1) Tạo một folder có tên ModuleA, trong thư mục ./module
Bước 2) Tạo 3 folder con thuộc thư mục ModuleA là config, src, view (không bắt buộc nhưng đây là cách tổ chức chuẩn, ý nghĩa giải thích ở các phần tiếp theo)
Bước 3) Trong thư mục ModuleA tạo file Module.php
là file để ModuleManager đọc và nạp với nội dung như sau:
≶?php namespace ModuleA; class Module { public function getAutoloaderConfig() { return [ 'Zend\Loader\ClassMapAutoloader' => [ __DIR__ . '/autoload_classmap.php'] ]; } public function getConfig() { return []; } }
Bước 4) Tạo ra file có tên autoload_classmap.php
trong ModuleA
, là nơi khai báo các đường dẫn đến các lớp của ModuleA,
nội dung nó như sau:
<?php return [ //... dẫn tới các lớp ];
Bước 5 tạo một lớp
Tạo ra một lớp tên ClassA
trong thư mục src
bằng cách tạo trong thư mục đó file ClassA.php
và cập nhật nội dung như sau:
<?php namespace ModuleA; class ClassA { public function __construct() { echo __CLASS__. ' đã khởi tạo thành công'; } }
Quay lại file: autoload_classmap.php, cập nhật thành
<?php return [ ModuleA\ClassA::class => __DIR__.'/src/ClassA.php', ];
Đến đây, bằng cách này bạn đã tạo ra một module có tên ModuleA
, giờ chỉ việc khai báo sử dụng
Ứng dụng
Mở file modules.config.php
trong thư mục config
gốc của dự án. Thêm vào cuối mảng tên module 'ModuleA'
Từ đây bạn đã có thể sử dụng các lớp của ModuleA
Ví dụ: Mở file IndexController.php
của module Application
, cập nhật phương thức indexAction()
thành:
public function indexAction() { new \ModuleA\ClassA(); return new ViewModel(); }
Kiểm tra thử kết quả trên trình duyệt, có dòng: ModuleA\ClassA đã khởi tạo thành công, như vậy thư viện, module đã nạp chính xác