Zend Framework 2 (ZF2) vừa ra mắt với khá nhiều thay đổi trong cách cấu trúc dự án và thư viện. Điều này mang đến nhiều điểm thuận lợi và hiệu quả hơn so với phiên bản Zend Framework 1. Trong bài này, ta sẽ cùng tìm hiểu một số đặc điểm của ZF2, cấu hình các thư viện và database.
Giới thiệu
Trang chủ: http://framework.zend.com/
ZF2 là một phiên bản thay đổi rất nhiều bởi việc sử dụng tính năng namespace của PHP 5.3 để tái cấu trúc lại thư viện Zend. Như vậy các tên lớp hay tập tin của ZF2 sẽ không dài ‘lòng thòng’ bằng cách ghép tên từng cấp thư mục lại với nhau nữa.
Trong ZF1, tập tin nằm ở cấp thư mục con thứ 4 thì tên của nó phải chứa 5 kí tự gạch dưới “_” (underscore), ví dụ như Zend_Db_Adapter_Pdo_Ibm_Db2. Trong ZF2, tập tin này chỉ cần đặt tên là Db2.
Cách sử dụng các lớp trong ZF2 cũng minh bạch hơn nhiều so với ZF1. Bạn sẽ cần dùng các từ khóanamespace và use để khai báo một namespace và chỉ ra các lớp sẽ được sử dụng.
Trong ZF1, các lớp được sử dụng sẽ tự động được “mò” ra bằng cách dựa vào tên của chúng.
ZF2 thay thế việc sử dụng các tập tin .ini bằng các tập tin .php để cấu hình. Điều này có thể giúp tăng tốc độ của việc đọc cấu hình, bởi vì việc đọc và chuyển nội dung của tập tin .ini thành đối tượng trong PHP tất nhiên sẽ chiếm thời gian nhiều hơn việc lấy một mảng dữ liệu PHP có sẵn.
Trong ZF1, tập tin nằm ở cấp thư mục con thứ 4 thì tên của nó phải chứa 5 kí tự gạch dưới “_” (underscore), ví dụ như Zend_Db_Adapter_Pdo_Ibm_Db2. Trong ZF2, tập tin này chỉ cần đặt tên là Db2.
Cách sử dụng các lớp trong ZF2 cũng minh bạch hơn nhiều so với ZF1. Bạn sẽ cần dùng các từ khóanamespace và use để khai báo một namespace và chỉ ra các lớp sẽ được sử dụng.
Trong ZF1, các lớp được sử dụng sẽ tự động được “mò” ra bằng cách dựa vào tên của chúng.
ZF2 thay thế việc sử dụng các tập tin .ini bằng các tập tin .php để cấu hình. Điều này có thể giúp tăng tốc độ của việc đọc cấu hình, bởi vì việc đọc và chuyển nội dung của tập tin .ini thành đối tượng trong PHP tất nhiên sẽ chiếm thời gian nhiều hơn việc lấy một mảng dữ liệu PHP có sẵn.
Chi tiết hơn ta sẽ cùng tìm hiểu qua các bài viết riêng. Bây giờ, về cấu trúc dự án trong ZF2, đã có khá nhiều bài viết hướng dẫn nhưng tốt nhất bạn nên đọc qua bài Getting Started with Zend Framework 2 cùng với dự án mẫu https://github.com/zendframework/ZendSkeletonApplication. Theo đó, một dự án ZF2 sẽ có dạng như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| zf2-project/ /config /autoload application.config.php /data /module /Foo /config /language /public /css /images /js /src /Foo /Controller /Form /Model /view /foo /index /about /error /layout Module.php /public index.php /vendor /ZF2 /library /Zend init_autoloader.php |
Như bạn thấy, dự án này hỗ trợ nhiều module rõ ràng và hiệu quả hơn so với ZF1. Để ứng dụng chặt chẽ hơn, các module bạn tạo ra phải được khai báo trong config/application.config.php. Tại cấp module, các controller và router cũng phải được khai báo/định nghĩa để được phép sử dụng trong config/module.config.php. Mỗi module được quản lý bởi tập tin Module.php . Tập tin này có nhiệm vụ nạp các thông tin, cấu hình cần thiết để module hoạt động.
Thêm thư viện dùng chung
Với mục đích tạo một thư viện dùng để xác thực người dùng trên nhiều dự án, tôi tạo một thư viện có tên AAC (Authentication & Authorization Control) và đặt nó trong đường dẫn vendor/Core/library/AAC.
Trong module cần sử dụng thư viện này (ví dụ module Admin), bạn mở tập tin Module.php (module/Admin/Module.php) và xem nội dung của phương thức getAutoloaderConfig(). Đây là hàm dùng để nạp các namespace và lớp cần sử dụng trong module.
Trong module cần sử dụng thư viện này (ví dụ module Admin), bạn mở tập tin Module.php (module/Admin/Module.php) và xem nội dung của phương thức getAutoloaderConfig(). Đây là hàm dùng để nạp các namespace và lớp cần sử dụng trong module.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // module/Admin/Module.php public function getAutoloaderConfig() { return array ( 'Zend\Loader\ClassMapAutoloader' => array ( __DIR__ . '/autoload_classmap.php' , ), 'Zend\Loader\StandardAutoloader' => array ( 'namespaces' => array ( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ), ); } |
Trong đó:
- Zend\Loader\ClassMapAutoloader: mảng này sẽ liệt kê các tập tin classmap, mỗi tập tin sẽ chứa một mảng các lớp cần được nạp.
- Zend\Loader\StandardAutoloader: tự động nạp các phần tử trong module hiện tại trong thư mục src (__NAMESPACE__ là từ khóa chứa tên namespace hiện tại, ở đây là Admin).
Ta sẽ thêm một phần tử vào mảng ‘Zend\Loader\StandardAutoloader’ để nạp các lớp trong thư viện ACC. Phương thức trên sẽ thành như sau:
- Zend\Loader\ClassMapAutoloader: mảng này sẽ liệt kê các tập tin classmap, mỗi tập tin sẽ chứa một mảng các lớp cần được nạp.
- Zend\Loader\StandardAutoloader: tự động nạp các phần tử trong module hiện tại trong thư mục src (__NAMESPACE__ là từ khóa chứa tên namespace hiện tại, ở đây là Admin).
Ta sẽ thêm một phần tử vào mảng ‘Zend\Loader\StandardAutoloader’ để nạp các lớp trong thư viện ACC. Phương thức trên sẽ thành như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // module/Admin/Module.php public function getAutoloaderConfig() { return array ( 'Zend\Loader\ClassMapAutoloader' => array ( __DIR__ . '/autoload_classmap.php' , ), 'Zend\Loader\StandardAutoloader' => array ( 'namespaces' => array ( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, 'AAC' => dirname(__DIR__) . '/../vendor/Core/library/AAC' , ), ), ); } |
Sử dụng nhiều kết nối dữ liệu
Thư viện AAC của tôi sẽ sử dụng một database riêng dùng để chứa các thông tin tài khoản, phân quyền,… Vì vậy khi được tích hợp vào các dự án khác, ta cần cấu hình thêm một kết nối database cho thư viện này.
Trong trường hợp này, tôi sẽ tạo một kết nối mới với tên aacdb bằng cách mở tập tin cấu hình của ứng dụng tại {my_project}/config/autoload/global.php. Sau đó thêm một phần tử mới:
Trong trường hợp này, tôi sẽ tạo một kết nối mới với tên aacdb bằng cách mở tập tin cấu hình của ứng dụng tại {my_project}/config/autoload/global.php. Sau đó thêm một phần tử mới:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // {my_project}/config/autoload/global.php return array ( 'aacdb' => array ( 'driver' => 'Pdo' , 'host' => 'YOUR_HOST' , 'dbname' => 'YOUR_DBNAME' , 'username' => 'yinyang' , 'password' => '987654321' , 'driver_options' => array ( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), // ... other configs ); |
Tiếp tục ta sẽ nạp dùng cấu hình này để tạo một kết nối (chính xác là một loại Data Adapter, nhưng bạn cũng có thể lưu trữ bất kì đối tượng nào khác) trong module Admin bằng cách thay đổi phương thức getServiceConfig() của tập tin Module.php.
Phương thức này sẽ trả về một mảng các cấu hình của ServiceManager dựa vào lớp Zend\ServiceManager\Config. ServiceManager có thể hiểu là một đối tượng có nhiệm vụ lưu giữ các cấu hình để sử dụng cho module. Bạn có thể cấu hình ServiceManager này trong module.config.php hoặc Module.php.
Phương thức này sẽ trả về một mảng các cấu hình của ServiceManager dựa vào lớp Zend\ServiceManager\Config. ServiceManager có thể hiểu là một đối tượng có nhiệm vụ lưu giữ các cấu hình để sử dụng cho module. Bạn có thể cấu hình ServiceManager này trong module.config.php hoặc Module.php.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // module/Admin/Module.php public function getServiceConfig() { return array ( 'factories' => array ( 'aacAdapter' => function ( $sm ) { $config = $sm ->get( 'config' ); $config = $config [ 'aacdb' ]; $dbAdapter = new DbAdapter( $config ); return $dbAdapter ; }, // ... ), ); } |
Khi cần lấy về accAdapter này, bạn có thể làm như sau trong Controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // ... class IndexController extends AbstractActionController { protected $accAdapter ; // ... public function getAacAdapter() { if (! $this ->accAdapter) { $sm = $this ->getServiceLocator(); $this ->accAdapter = $sm ->get( 'aacAdapter' ); } return $this ->adminTable; } } |
Comments[ 0 ]
Đăng nhận xét