Lập trình web nâng cao - Bài 1: Tổng quan Zend Framework 2 (ZF2)

Tài liệu Lập trình web nâng cao - Bài 1: Tổng quan Zend Framework 2 (ZF2): TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 1 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM Bài 1: Tổng quan Zend Framework 2 (ZF2) 1. Giới thiệu ZF 2. Lý do chọn ZF 3. Giới thiệu ZF2 4. Zend MVC 5 Cài đặt và cấu hình ZF2. 2 Bài 1: Tổng quan ZF2 1 Giới thiệ ZF. u  Zend Framework là một PHP Framework đuợc lập trình bằng ngôn ngữ PHP và dựa trên mô hình MVC, giúp tách các thành phần xử lý ra một cách rõ ràng cho website của bạn, giúp cho code được dễ dàng quản lý, chỉnh sửa và nâng cấp. – Sử dụng PHP 5 – Viết huớng đối tuợng – Cung cấp mô hình tiên tiến MVC – Là 1 phần mềm nguồn mở có sự hỗ trợ cộng đồng – Cung cấp 1 loạt các ứng dụng API của các nhà cung cấp hàng đầu như Google, Yahoo, Flick... 3 Bài 1: Tổng quan ZF2 Sử d ZF để ụng Tạo ứng dụng web theo mô hình chuẩn MVC– – Url tiêu chuẩn, ngắn gọn ỗ ề– H trợ phân quy n tới từng Action – Có các thành phần thư viên hỗ trợ API của các nhà...

pdf403 trang | Chia sẻ: Khủng Long | Lượt xem: 2294 | Lượt tải: 1download
Bạn đang xem trước 20 trang mẫu tài liệu Lập trình web nâng cao - Bài 1: Tổng quan Zend Framework 2 (ZF2), để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 1 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM Bài 1: Tổng quan Zend Framework 2 (ZF2) 1. Giới thiệu ZF 2. Lý do chọn ZF 3. Giới thiệu ZF2 4. Zend MVC 5 Cài đặt và cấu hình ZF2. 2 Bài 1: Tổng quan ZF2 1 Giới thiệ ZF. u  Zend Framework là một PHP Framework đuợc lập trình bằng ngôn ngữ PHP và dựa trên mô hình MVC, giúp tách các thành phần xử lý ra một cách rõ ràng cho website của bạn, giúp cho code được dễ dàng quản lý, chỉnh sửa và nâng cấp. – Sử dụng PHP 5 – Viết huớng đối tuợng – Cung cấp mô hình tiên tiến MVC – Là 1 phần mềm nguồn mở có sự hỗ trợ cộng đồng – Cung cấp 1 loạt các ứng dụng API của các nhà cung cấp hàng đầu như Google, Yahoo, Flick... 3 Bài 1: Tổng quan ZF2 Sử d ZF để ụng Tạo ứng dụng web theo mô hình chuẩn MVC– – Url tiêu chuẩn, ngắn gọn ỗ ề– H trợ phân quy n tới từng Action – Có các thành phần thư viên hỗ trợ API của các nhà cung cấp như Google, Yahoo, Flick – Quản lý code dễ dàng, liệt kê và lấy các truy vấn history Dễ dàng phát triển thêm các ứng dụng nhúng– , sử dụng Plugins 4 Bài 1: Tổng quan ZF2 2 Lý d h ZF. o c ọn – Có rất nhiều thư viện được hỗ trợ sẵn – Là một PHP Framework được do chính công ty phát triển ngôn ngữ PHP phát triển (www.zend.com). – được xây dựng trên nền tảng lập trình hướng đối tượng nên có thể thừa kế, nâng cấp các ứng dụng một cách dễ dàng. – Những thành viên phát triển Zend Framework là những chuyên gia nổi tiếng về mã nguồn mở và PHP trên thế giới. ẩ– Mô hình MVC hoặc không theo chu n MVC trong Zend Framework rất linh hoạt giúp chúng ta có thể tùy biến cấu hình ứng dụng theo ý muốn . 5 Bài 1: Tổng quan ZF2 2 Lý d h ZF. o c ọn – Tích hợp các thư viện các thành phần khác một cách , linh hoạt và nhanh chóng. – Có tài liệu để tham khảo – Cộng đồng người sử dụng Zend Framework lớn. – Những ứng dụng lớn hiện nay đã dần chuyển qua dùng Zend Framework làm nền tảng. – Nhu cầu tuyển dụng lập trình viên biết Zend Framework lớn – Bảo mật của các ứng dụng rất tốt nên tránh được các lỗi thường gặp trong các ứng dụng viết bằng PHP thường. 6 Bài 1: Tổng quan ZF2 3 Giới thiệ ZF2. u Zend Framework 2 là một framwork mã– nguồn mở dùng cho việc phát triển các ứng dụng web sử dụng PHP 5 3 x zend . . . Framework được xây dựng hoàn toàn theo hướng đối tượng OOP và sử dụng hầu hết các đặc điểm mới của PHP 5.3 như namespaces late static binding phương thức, , lambda và closures. Z d F k 2 hát t iể từ Z d– en ramewor p r n en Framework 1, một framework PHP rất thành ô ới h 15 t iệ l t tải ềc ng v ơn r u ượ v . 7 Bài 1: Tổng quan ZF2 Đặ điể ZF2c m  Cấu trúc mới: – Theo mô hình MVC, sử dụng Di, Events, Service, Module  Cải tiến về chức năng  Sử dụng PHP 5 3 3 . .  PSR – 2 compliant (hỗ trợ pyrus, composer)  Hệ thống đóng gói  ZF được viết theo kiểu OOP nên nó thừa hưởng các thế mạnh của kiểu viết này. Các lớp của ZF được BA (Business Analysis) rất chuẩn và khi cần mở rộng ta có thể dùng thể dùng tính chất thừa kế của OOP. Nói chung là ta không phải chỉnh sửa core của ZF. 8 Bài 1: Tổng quan ZF2 Đặ điể ZF2c m  Hầu như các version mới của ZF không có nhiều thay đổi trong core nên ta có thể dễ dàng update.  ZF tích hợp được gần như tất cả các thư viện PHP và các CMS khác để sử dụng. VD: Smarty - Pear - FCKEditor - Drupal  Cách viết của ZF rất thân thiện và đơn giản. Tích hợp những mới nhất của lập trình web như: JSON - Search - S di ti W b S iyn ca on - e erv ces...  ZF được sử dụng trong các dự án lớn và có kế hoạch phát triển dài lâu 9 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Kiến trúc MVC của ZF2 10 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Zend\Mvc là một nhánh thực hiện MVC mới được thiết kế cho ZF2, tập trung vào hiệu suất và tính linh hoạt .  MVC layer được xây dựng ở phía trên của các thà h hần p n sau: – Zend\ServiceManager – ZF2 cung cấp một bộ các định nghĩa dịch mặc định đ ợc thiết lập ở vụ ư Zend\Mvc\Service. ServiceManager tạo và cấu hình instance và workflow trong ứng dụng . 11 Bài 1: Tổng quan ZF2 4 Z d MVC. en – Zend\EventManager – MVC là một event driven . Thành phần này được sử dụng mọi nơi từ khởi tạo ban đầu của ứng dụng, thông qua việc gọi trả về của response và request, để thiết lập và nhận các định tuyến và các định tuyến phù hợp (tương ứng), cũng h d á in ư ren er c c v ew. – Zend\Http – đặc biệt là các đối tượng request và response được sử dụng trong:, – Zend\Stdlib\DispatchableInterface. Tất cả các “controller” đơn giản là đối tượng dispatchable . 12 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Trong MVC layer có một số thành phần con , được giới thiệu: Zend\Mvc\Router chứa các lớp liên quan đến định– tuyến một request. Nói cách khác, nó nối các request tới các controller tương ứng của nó (hoặc dispatchable). – Zend\Http\PhpEnvironment cung cấp một bộ decorator cho các đối tượng HTTP Request và Response nhằm đảm bảo là các request được đưa à ôi t ờ hiệ t i (b ồ áv o m rư ng n ạ ao g m c c query parameter, POST parameter, HTTP header..) 13 Bài 1: Tổng quan ZF2 4 Z d MVC. en – Zend\Mvc\Controller một bộ các lớp “controller” trừu, tượng với các trách nhiệm cơ bản như hệ thống các event, action gửi đi – Zend\Mvc\Service cung một bộ các yếu tố và định nghĩa ServiceManager workflow của ứng dụng mặc định. – Zend\Mvc\View cung cấp các thông số mặc định cho d l ti độ hâ iải i i t đă kýren erer se ec on, p n g v ew scr p , ng helper; ngoài ra, nó cung cấp các listener liên lạc với MVC workflow cung cấp các tính năng như phân , giải tên template tự động, tạo view model tự động... 14 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Gateway của MVC là đối tượng Zend\Mvc\Application (gọi tắt là “Application”). Nhiệ hí h ủ “A li ti ” là khởi t á m vụ c n c a pp ca on ạo c c tài nguyên, định tuyến request, nhận và gửi t ll hù h t á á t ì h đị hcon ro er p ợp rong c c qu r n n tuyến. Sau khi hoàn thành, nó sẽ render view, h à thà h á t t ả ề à ửio n n c c reques , r v v g response. 15 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Cấu trúc ứng dụng cơ bản: 16 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Cấu trúc ứng dụng cơ bản: – Tập tin public/index.php: gồm tất cả các yêu cầu (request) của người dùng đến website nhận một , mảng các cấu hình đặt tại tập tin config/application.config.php, khi trả về nó gọi phương thức run() của “Application”, xử lý yêu cầu và gửi lại phản hồi cho người dùng. ấ– Thư mục config chứa c u hình được sử dụng bởi Zend\ModuleManager để tải các module và cấu hình hợp nhất . 17 Bài 1: Tổng quan ZF2 4 Z d MVC. en – Thư mục vendor : chứa các module hoặc thư viện của tổ chức thứ ba mà ứng dụng cần dùng tới. Nó có thể bao gồm cả ZF hoặc các thư viện từ các dự án khác, không nên sửa đổi trạng thái ban đầu của các thư viện và module đặt trong thư mục vendor chúng. ề– Thư mục module: chứa một hoặc nhi u module cung cấp các chức năng của ứng dụng 18 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Cấu trúc module cơ bản: – Trong một module có thể chứa: code PHP, gồm cả chức năng MVC code thư viện view script và các tài , , nguyên chung như: hình ảnh, CSS, JavaScript. Yêu cầu duy nhất – có thể là tùy chọn là một module hoạt động như một namespace PHP và nó chứa lớp Module.php dưới namespace. Lớp này được Z d\M d l M ử d để th hiệ ột ốen o u e anager s ụng ực n m s nhiệm vụ. 19 Bài 1: Tổng quan ZF2 4 Z d MVC. en 20 Bài 1: Tổng quan ZF2 4 Z d MVC. en – Khi một module hoạt động như một namespace thư , mục module cũng phải có tên là tên của namespace. Namespace này cũng có thể bao gồm một tiền tố của nhà cung cấp. • Ví dụ: Module liên quan đến “User” có chức năng được cung ấ bởi Z d thì ó thể đặt tê là “Z dU ”c p en c n en ser . – Tập tin Module.php sẽ nằm trong thư mục – namespace này . namespace ZendUser; class Module { 21 } Bài 1: Tổng quan ZF2 4 Z d MVC. en  Có ba tập tin autoload * php không bắt buộc _ . , nhưng khuyến khích nên có, đó là: autoload classmap php: trả về mảng classmap của– _ . các cặp class name/filename (với các tên tập tin được thông qua hằng số DIR ). __ __ – autoload_function.php: trả về một callback PHP mà có thể thông qua spl autoload register(). Thông _ _ thường callback này nên sử dụng ánh xạ được trả về bởi autoload_classmap.php. – autoload_register.php: nên đăng ký một PHP callback (thường được trả về bởi autoload function php với spl autoload register())_ . _ _ . 22 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Đặc điểm của ba file này là cung cấp các cơ chế mặc định phù hợp để tự động tải các lớp trong module do đó cung cấp cách thức dễ dàng để, thực thi module mà không cần Zend\ModuleManager 23 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Thư mục config: nên chứa các cấu hình module cụ thể. Các file này có đĩnh dạng được hỗ trợ của Zend\Config Cấu hình chính nên là . “module.format”, và cấu hình dựa trên PHP nên là “module config php” . . .  Thư mục src: tuân thủ cấu trúc thư mục chứa d ủ d l Nê ó ít hất ột thsource co e c a mo u e. n c n m ư mục con trong thư mục namespace. 24 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Thư mục view: chứa các view script có liên quan tới các controller. Th t t hứ á it t t ủ ứ d ư mục es : c a c c un es c a ng ụng. Thông thường sử dụng PHPUnit, và chứa các ế tố liê đế ấ hì h ủ ó ( í d hy u n quan n c u n c a n v ụ n ư phpunit.xml, bootstrap.php)  Thư mục public: chứa những thứ dùng chung cho ứng dụng, có thể là thư mục images, CSS, JavaScript 25 Bài 1: Tổng quan ZF2 4 Z d MVC. en  Khởi tạo một module trong ứng dụng – Để khởi tạo một module trong ứng dụng, ta thông qua Zend\ModuleManager\ModuleManager. – Thành phần này cho phép ta chỉ đến nơi module đó tồn tại Sau đó nó sẽ xác định vị trí module và khởi . tạo. Các lớp module có thể gắn vào các listener khác nhau trên ModuleManager để cung cấp thông tin, service, listener cho ứng dụng. 26 Bài 1: Tổng quan ZF2 4 Z d MVC. en – Cấu hình module manager • Cấu hình module manager: đơn giản chỉ cần thông báo cho module manager biết module nào để tải và có khả năng cung ấ ấc p c u hình cho module listener. • Trong tập tin application.config.php, ta cung cấp các thông tin cấu hình: // config/application.config.php return array( Khi thêm các module vào hệ 'modules' => array( /* ... */ ), ' d l li t ti ' ( thống, ta sẽ thêm các item này vào mảngmo u e_ s ener_op ons => array 'module_paths' => array( './module', ' / endor' “modules”. 27 . v , ),),); Bài 1: Tổng quan ZF2 4 Z d MVC. en  Mỗi lớp “Module” có cấu hình mà nó muốn “Application” biết sẽ được khai báo trong phương thức getConfig(). Phương thức này sẽ trả về một mảng hoặc một đối tượng Traversable như Zend\Config\Config. namespace ZendUser; class Module { public function getConfig() { return include __DIR__ . '/config/module.config.php' } }  Ngoài ra còn có nhiều phương thức khác có thể định nghĩa để cung cấp thông tin autoloader, service cho ServiceManager  28 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n  Các bước thực hiện – Download và cài đặt Wamp Server 2.1 (WampServer2.1e-x32.exe) – Vào Apache modules trong wamp server => bật module rewrite_module – Download zend freamwork 2.x tại – Download ứng dụng mẫu (Skeleton Application) của zend framework 2.x tại https://github com/zendframework/ZendSkelet. onApplication 29 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n Giải nén ứng dụng mẫu vào thư mục lưu trữ– web Cấ t ú â th ứ d ẫ– u r c c y ư mục ng ụng m u: 30 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n Trong đó:– 31 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n Tạo thư mục library trong ứng dụng này sau– đó đem gói zend framework 2.x giải nén tại đây 32 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n  Chú ý: Nếu muốn sử dụng thư viện một Zend cho tất cả các ứng dụng thì cần phải tạo ra một biến toàn cục như sau: – Vào Computer => Properties => Advanced => E i t V i bl > N > T biếnv ronmen ar a es = ew = ạo n mới => OK 33 Ví dụ: ZF2_PATH = H:\wamp\www\\ZendSkeletonApplication01112012\library Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n  Chú ý (tt) – Nếu muốn sử dụng riêng cho từng website thì ỗ ầ ảm i website ta c n ph i có một thư mục Library\Zend trong Library chứa các thư viện ủc a Zend Framwork 2.x đặt tại: H:\wamp\www\PHP_NC\zend_app vendor\ZF2 34 Bài 1: Tổng quan ZF2 5 Cài đặt à ấ hì h ZF2. v c u n  Kết quả sau khi cài đặt và cấu hình thành công: 35 Bài 1: Tổng quan ZF2 36 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 1 LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 2 Bài 2: Zend Module 1. Zend Module 2. Xây dựng module cho ứng dụng 3. Zend Module Manager 4. Zend Module Autoloader 5. Cấu hình cho module 6. Thông báo về việc có module mới Bài 2: Zend Module 3 1. Zend Module Khái niệm:  Module là một nhóm trong đó có chứa các thành phần của website phục vụ cho một chức năng hoàn chỉnh nào đó.  ZF2 giới thiệu một cách tiếp cận mới và rất mạnh mẽ cho các module.  Hệ thống mới này được thiết kế mềm dẻo, linh hoạt, đơn giản và dễ dàng tái sử dụng.  Module có thể chứa: code PHP - theo mô hình MVC, thư viện code, view script và các tài nguyên dùng chung như hình ảnh, CSS, và JavaScript. Bài 2: Zend Module 1. Zend Module  Trong ZF2 tất cả đều được tối ưu hóa thành module. Người dùng có thể tự xây dựng module cho mình hoặc có thể chép module của người khác về ứng dụng để phục vụ cho công việc của mình.  Hệ thống module được tạo thành như sau: – Module Autoloader – Module Manager – ModuleManager Listeners 4 Bài 2: Zend Module 1. Zend Module  Trong đó: – Module Autoloader: Đây là thành phần đặc biệt giúp cho việc xử lý các namespace, mapping, và giữ các instances đó khi cần xử lý ... – Module Manager: Thành phần này có chức năng quản lý module, quản lý và merger các cấu hình của các module, điều khiển việc loader ... – ModuleManager Listeners – Các Event listener có thể được gắn với các sự kiện khác nhau của module manager. Những listener có thể làm mọi việc từ việc giải quyết và load các module tới việc thực hiện khởi tạo các task phức tạp. 5 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Zend framework sử dụng hệ thống module và ta sẽ tổ chức các nội dung chính của ứng dụng trong các module.  Trong gói mẫu đã cài đặt có Module Application, được cung cấp bởi Skeleton, nó cung cấp các định nghĩa và cấu hình chuẩn mà một module cần phải có (bootstrapping, error và routing configuration), đồng thời cung cấp các các điều khiển cần cho ứng dụng. 6 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Tuy nhiên, ta sẽ chỉ tham khảo module này để tạo và làm riêng một module và thực hiện các chức năng cần thiết trong module riêng.  Ta sẽ đặt tất cả các code cần thiết vào module của chúng ta, nơi chứa các controller, model, form và view kèm theo các cấu hình (configuration).  Ta cũng sẽ tinh chỉnh module Application khi được yêu cầu. 7 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Ví dụ: Xây dựng ứng dụng đầu tiên với Zend Framework có kết nối đến CSDL –Ứng dụng sẽ xây dựng là một cửa hàng bán tranh. Trang chính sẽ liệt kê các tranh mà cửa hàng có bán. Cửa hàng có thể hiển thị, thêm, xóa và cập nhật Tranh khi cần. 8 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Theo yêu cầu trên, sẽ có 4 trang trong ứng dụng: – Danh mục tranh, kèm theo link để người dùng có thể xem chi tiết; nếu là quản trị thì có thể thêm, xóa, cập nhật – Thêm mới tranh: form dùng để thêm mới – Cập nhật tranh: form dùng để cập nhật – Xóa tranh: form dùng để xóa 9 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Cần phải lưu trữ dữ liệu vào CSDL đơn giản như sau: Bảng Product (để lưu các tranh) – ProductID: mã số tranh – ProductName: tên tranh – Description: mô tả – Price: giá – Amount: số lượng 10 Bài 2: Zend Module 2. Xây dựng module cho ứng dụng  Thực hiện module – Bước 1: Xây dựng cây thư mục sau cho ứng dụng 11 Zend_app/ /module /Product /config /src /Product /Controller /Form /Model /view /product /product Module Product có các thư mục con với những loại file khác nhau. Các file PHP chứa các lớp trong namespace Product đặt ở thư mục src/Product. Có thể có nhiều namespace khác nhau trong thư mục này. Thư mục view cũng có một thư mục con gọi là product chứa các view cho module. Bài 2: Zend Module 3. Zend Module Manager  Để load và cấu hình một module, ZF2 có ModuleManager.  Module này có thể xem như là file Module.php đặt trong thư mục gốc của module. – Ví dụ: module/Product và có một class được gọi là Product/Module bên trong nó.  Các lớp trong cùng một module sẽ có namespace có tên là tên của module (tên thư mục cũng là tên của module) 12 Bài 2: Zend Module 3. Zend Module Manager  Thực hiện module (tt) – Bước 2: Xây dựng Module.php nằm trong module Product 13 namespace Product; class Module{ public function getAutoloaderConfig(){ return array( 'Zend\Loader\ClassMapAutoloader' => array( __DIR__ . '/autoload_classmap.php‘, ), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array( __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, ), ),); } public function getConfig(){ return include __DIR__ . '/config/module.config.php'; }} //ModuleManager sẽ tự động gọi phương thức getAutoloaderConfig() và getConfig() Bài 2: Zend Module 4. Zend Module Autoloader  Phương thức getAutoloaderConfig() trả về một mảng tương thích với AutoloaderFactory. Cần phải cấu hình để có thể thêm class map file vào ClassmapAutoloader và đồng thời thêm namespace của module này vào StandardAutoloader.  Autoloader chuẩn yêu cầu phải có một namespace và một đường dẫn để có thể tìm thấy các file của namespace này. Đó là tuân thủ theo PSR-0 và để các lớp map trực tiếp đến các files theo các quy tắc của PSR-0.  Khi triển khai ứng dụng, ta không cần phải load các file thông qua classmap, vì thế ta chỉ cần cung cấp một mảng rỗng cho classmap autoloader. 14 Bài 2: Zend Module 4. Zend Module Autoloader  Thực hiện module (tt) – Bước 3: Tạo file autoload_classmap.php có nội dung sau: – Với một mảng rỗng như trên thì bất cứ khi nào autoloader tìm kiếm lớp trong Product namespace, nó sẽ tự động gọi trở lại StandardAutoloader. 15 // module/Product/autoload_classmap.php: return array(); Bài 2: Zend Module 4. Zend Module Autoloader  Chú ý: – Ta đang sử dụng Composer, như là một sự thay thế, ta không triển khai (implement) getAutoloaderConfig() và thay vào đó ta thêm "Application": "module/Application/src" vào psr-0 key trong composer.json. – Nếu ta chọn cách này, thì ta cần phải chạy php composer.php update để cập nhật composer autoloading files. 16 Bài 2: Zend Module 5. Cấu hình cho module  Sau khi đã đăng ký autoloader, ta xem xét đến phương thức getConfig() trong Product\Module.  Phương thức này dùng để load file config/module.config.php 17 Bài 2: Zend Module 5. Cấu hình cho module  Thực hiện module (tt) – Bước 4: Tạo file cấu hình trong module Product 18 // module/Product/config/module.config.php: return array( 'controllers' => array( 'invokables' => array( 'Product\Controller\Product' => 'Product\Controller\ProductController', ), ), 'view_manager' => array( 'template_path_stack' => array( 'product' => __DIR__ . '/../view', ), ), ); Bài 2: Zend Module 6. Thông báo về việc có module mới  Ta cần phải thông báo với ModuleManager là có một module mới vừa được xây dựng.  Công việc này được thực hiện ở file config/application.config.php của Application, nơi cung cấp skeleton của ứng dụng. 19 Bài 2: Zend Module 6. Thông báo về việc có module mới  Thực hiện module (tt) – Bước 4: Cập nhật file config/application.config.php để “modules” có chứa module Product. 20 // config/application.config.php của ứng dung return array( 'modules' => array( 'Application', 'Product', // <-- Thêm vào dòng này ), 'module_listener_options' => array( 'config_glob_paths' => array( 'config/autoload/{,*.}{global,local}.php‘, ), 'module_paths' => array( './module', './vendor', ), ), ); Bài 2: Zend Module 21 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 1 LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 2 Bài 3: Routing và Controller 1. Routing 2. Controller 3. View Bài 3: Routing và Controller 3 1. Routing  ZF2 có một bộ máy ánh xạ URL rất mạnh mẽ. Bộ máy này cung cấp phương pháp rất linh hoạt trong việc ánh xạ URLs sang cho Controller.  Ta có thể dễ dàng định ra các quy luật ánh xạ, cài đặt để ZF2 dựa vào các quy luật ánh xạ đó, xác định xem phải thực thi action nào.  ZF2 còn có khả năng phân tích URL, chuyển các thông số trong URL thành các tham số trong phần gọi hàm của Controller. Bài 3: Routing và Controller 1. Routing  Cách thức làm việc của trang theo ZF2: – Mỗi trang trong ứng dụng được xem như một hành động và các hành động này được nhóm vào các controllers trong các module. – Vì vậy, ta cần phải nhóm các hành động có liên quan vào cùng một controller. – Một controller có thể có các hành động: current, archived, view 4 Bài 3: Routing và Controller 1. Routing  Thực hiện (tt) – Bước 6: với ví dụ đã nêu ở bài Module, ta có 4 trang: hiển thị, thêm, cập nhật và xóa; ta nhóm chúng vào cùng một ProductController và đặt các action dành cho việc quản lý tranh lần lượt như sau: index, add, edit, delete – Việc mapping của một URL để một hành động cụ thể được thực hiện bằng cách sử dụng các định tuyến (routes) được định nghĩa trong tập tin module.config.php của module. Ta sẽ thêm vào một route cho những hành động của Product tại tập tin cấu hình module này. 5 Bài 3: Routing và Controller 6 // module/Product/config/module.config.php 'router' => array( 'routes' => array( 'product' => array( 'type' => 'segment', 'options' => array( 'route' => '/product[/:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Product\Controller\Product', 'action' => 'index', ), ), ), ), ), ); Tên của route là “product” và có kiểu là “segment”. Segment cho phép ta chỉ định giữ chỗ trong URL pattern (route) sẽ được map tới các tham số được đặt tên. Bài 3: Routing và Controller 1. Routing  Ví dụ: Trong trường hợp này, route là ``/product[/:action][/:id]`` sẽ dẫn đến nơi có URL bắt đầu bằng /product.  Segment tiếp theo sẽ map tới id tùy chọn.  Trong công thức trên, với những segment được đặt trong dấu ngoặc vuông được hiểu là các segment tùy chọn.  Các session ràng buộc giúp đảm bảo các ký tự bên trong của segment như mong muốn, và ta có một số lượng giới hạn các hành động bắt đầu bằng ký tự, sau đó là chữ số, gạch dưới hay gạch nối. Ta cũng giới hạn id cho một số. 7 Bài 3: Routing và Controller 1. Routing  Ví dụ: Việc định tuyến cho ta những URL dưới đây: 8 URL Page Action /product Trang chủ (Danh sách các sản phẩm tranh) index /product/add Thêm một sản phẩm tranh mới add /product/edit/2 Cập nhật sản phẩm tranh có id là 2 edit /product/delete/4 Xóa sản phẩm tranh có id là 4 delete Bài 3: Routing và Controller 2. Controller  Trong ZF2, controller là một lớp có cú pháp tên gọi như sau: {Controller name}Controller. Với: – {Controller name}: bắt đầu bằng chữ cái viết hoa – Lớp này nằm trong file có tên là {Controller name}Controller.php đặt trong thư mục Controller của module. Ví dụ: Trong trường hợp này thì lớp controller sẽ đặt tại module/Product/src/Product/Controller. – Mỗi action là một phương thức toàn cục của lớp controller và có cú pháp tên gọi {action name}Action, với {action name} bắt đầu bằng chữ cái viết thường. 9 Bài 3: Routing và Controller 2. Controller  Chú ý: Theo quy ước, ZF2 không cung cấp quá nhiều ràng buộc trên controller, mà họ phải thực hiện (implement) Zend\Stdlib\Dispatchable interface.  ZF2 cung cấp hai lớp trừu tượng để thực hiện công việc này cho ta là Zend\Mvc\Controller\AbstractActionController và Zend\Mvc\Controller\AbstractRestfulController.  Ta sẽ sử dụng AbstractActionController chuẩn, nhưng nếu dự định sẽ viết RESTful web service thì có thể sử dụng AbstractRestfulController. 10 Bài 3: Routing và Controller 2. Controller  Thực hiện (tt) – Bước 7: Xây dựng controller của Product 11 // module/Product/src/Product/Controller/ProductController.php namespace Product\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; class ProductController extends AbstractActionController { public function indexAction() { } public function addAction() { } public function editAction() { } public function deleteAction() { } } Chú ý: Ta đã thông báo về controller này trong phần ‘controller’ tại config/module.config .php ở phía trên. Bài 3: Routing và Controller 3. Tạo view  Tiếp theo cần phải thiết lập các action mà chúng ta muốn dùng bằng cách xây dựng các views.  Khởi tạo các Views – Để kết nối view vào ứng dụng, ta cần phải tạo ra các view script file. Những file này sẽ được thực thi bởi DefaultViewStrategy và các biến hoặc view model sẽ được chuyển sang từ phương thức của controller. – Những view script này được lưu trữ trong thư mục view của module. 12 Bài 3: Routing và Controller 3. Tạo view  Thực hiện (tt) – Ví dụ: Chuẩn bị các file cho các view script như sau: • module/Product/view/product/product/index.phtml • module/Product/view/product/product/add.phtml • module/Product/view/product/product/edit.phtml • module/Product/view/product/product/delete.phtml – Chú ý: Nội dung của các file này sẽ được điền sau, sau khi đã kết nối với CSDL và viết nội dung cho model. 13 Bài 3: Routing và Controller 14 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 1 LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 2 Bài 4: Database và Model ZendDbAdapter Bài 4: Database và Model 3 1. ZendDbAdapter Giới thiệu:  Đối tượng Adapter là một thành phần (sub-component) quan trọng nhất của Zend\Db. Nó chịu trách nhiệm thích ứng các code được viết trong Zend\Db tới các phần mở rộng PHP đích và cơ sở dữ liệu từ nhà cung cấp.  Để thực hiện việc này, nó tạo ra một lớp trừu tượng cho các thành phần mở rộng PHP, được gọi là "Driver" của Zend\Db adapter. Nó cũng tạo ra một lớp trừu tượng, được gọi là "Platform" của adapter, cho các nguồn khác nhau mà mỗi nhà cung cấp platform cụ thể có thể có trong việc thực hiện SQL / RDBMS. Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Tạo một adapter đơn giản bằng cách sử dụng lớp Zend\Db\Adapter\Adapter. Trường hợp phổ biến nhất là thông qua một mảng cấu hình cho Adapter.  Mảng này là một trừu tượng với các tham số yêu cầu ở mức mở rộng. 4 $adapter = new Zend\Db\Adapter\Adapter($configArray); Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Bảng dưới đây là các giá trị nên có trong mảng cấu hình: 5 Từ khóa Yêu cầu/ không yêu cầu phải có? Giá trị driver Yêu cầu Mysqli, Sqlsrv, Pdo_Sqlite, Pdo_Mysql, Pdo=OtherPdoDriver database Thường yêu cầu Tên của CSDL username Thường yêu cầu Tên đăng nhập khi kết nối password Thường yêu cầu Mật khẩu hostname Không thường yêu cầu Địa chỉ IP hoặc hostname kết nối tới port Không thường yêu cầu port charset Không thường yêu cầu Bộ ký tự sử dụng Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Ví dụ: Kết nối tới MySQL sử dụng ext/mysqli: 6 $adapter = new Zend\Db\Adapter\Adapter(array( 'driver' => 'Mysqli', 'database' => 'zend_db_example', 'username' => 'developer', 'password' => 'developer-password' )); Danh sách các Driver được hỗ trợ: •Mysqli: ext/mysqli driver •Pgsql: ext/pgsql driver •Sqlsrv: ext/sqlsrv driver (from Microsoft) •Pdo_Mysql: MySQL thông qua mở rộng PDO •Pdo_Sqlite: SQLite thông qua mở rộng PDO •Pdo_Pgsql: PostgreSQL thông qua mở rộng PDO Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Chú ý: – Sử dụng cách này để tạo adapter, lớp Adapter sẽ cố gắng để tạo ra bất kỳ phụ thuộc nào dù không được nêu rõ ràng. – Một đối tượng Driver sẽ được tạo ra từ mảng cấu hình được cung cấp trong constructor. Một đối tượng Platform sẽ được tạo ra dựa vào kiểu của lớp instantiated. – Một đối tượng mặc định ResultSet được tạo ra và sử dụng. Các đối tượng khác cũng có thể được thêm vào. 7 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Chuẩn bị câu lệnh truy vấn thông qua Zend\Db\Adapter\Adapter::query() – Mặc định, query() là thứ mà ta chuẩn bị sẵn và xem như một phương tiện để xử lý các câu lệnh SQL. Ta sẽ cung cấp một câu lệnh SQL với các giá trị được thay thế bằng các placeholder, các tham số. – Ví dụ về quy trình làm việc với Zend\Db\Adapter\Adapter này là: 8 $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', array(5)); Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Ví dụ này được thực hiện thông qua các bước sau: – Tạo ra một đối tượng Statement mới – Chuẩn bị một mảng để truyền vào ParameterContainer nếu cần – Đưa ParameterContainer vào đối tượng Statement – Thực thi đối tượng Statement, tạo ra một đối tượng kết quả Result – Kiểm tra đối tượng Result để kiểm tra xem sql được cung cấp có phải là một “query” (lấy dữ liệu), hay là một bộ các statement được tạo ra (thêm, cập nhật hoăc xóa dữ liệu). – Nếu kết quả là một bộ câu lệnh truy vấn được tạo ra thì sao chép ResultSet prototype, đưa Result vào như nguồn dữ liệu, trả về (trường hợp thêm, cập nhật hoặc xóa dữ liệu) – Ngược lại, trả về Result (trường hợp lấy dữ liệu để hiển thị) 9 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Thực thi câu lệnh truy vấn thông qua Zend\Db\Adapter\Adapter::query() – Trong một vài trường hợp ta cần phải thực thi ngay các statement. – Mục đích chính của việc thực thi ngay câu lệnh truy vấn thay vì phải chuẩn bị rồi mới thực thi là vì có thể ta đang cố gắng thực thi một DDL statement (trong hầu hết các extension và các vendor platform, mà không cần chuẩn bị. 10 Bài 4: Database và Model Ví dụ 1  Xóa khách hàng có MaKH=27 Controller: try { $adapter = new \Zend\Db\Adapter\Adapter(array( 'driver' => 'Mysqli', 'database' => 'fashion', 'username' => 'root', 'password' => '' )); $result=$adapter->query("delete from user where id=?", array(27), $adapter::QUERY_MODE_EXECUTE); } catch (Exception $e) { echo 'Khong ket noi duong'; } return new ViewModel(array('results'=>$result)); 11 Bài 4: Database và Model  View if($results->getAffectedRows()>0) { echo 'xoa thanh cong'; } else echo 'xoa khong thanh cong'; 12 Ví dụ 1 Bài 4: Database và Model Ví dụ 2: Liệt kê danh sách User  Controller try { $adapter = new \Zend\Db\Adapter\Adapter(array( 'driver' => 'Mysqli', 'database' => 'fashion', 'username' => 'root', 'password' => '' )); $result=$adapter->query("select * from user",$adapter::QUERY_MODE_EXECUTE); } catch (Exception $e) { echo 'Khong ket noi duong'; } return new ViewModel(array('results'=>$result)); 13 Bài 4: Database và Model 14 Ví dụ 2: Liệt kê danh sách User  View <?php if($results->count()>0) { foreach ($results as $row) { echo $row->id . ' | '; echo $row->username . ''; } } Bài 4: Database và Model Ví dụ 3  Xóa khách hàng có MaKH=27 File controller public function indexAction() { $auth = new AuthenticationService(); if ($auth->hasIdentity()) { $lienheTable = new LienheTable(); $sm=$this->getServiceLocator(); $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $result = $lienheTable->delete($dbAdapter); print_r($result); } else echo 'chua'; return new ViewModel(); } 15 Bài 4: Database và Model  File model LienheTable public function delete($adapter) { return $adapter->query( 'delete FROM Khachhang where MaKH=?', array(27), $adapter::QUERY_MODE_EXECUTE); } 16 Ví dụ 3 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn – Ví dụ: – Một khác biệt duy nhất cần chú ý là ta cần phải cung cấp Adapter::QUERY_MODE_EXECUTE (execute) là tham số thứ hai. 17 $adapter->query('ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE); Bài 4: Database và Model 3. Tạo Statement  Trong khi query() rất hữu ích khi thực hiện truy vấn nhanh một lần tới CSDL thông qua Adapter, nó thường có ý nghĩa hơn khi tạo ra một statement và tương tác trực tiếp để ta có thể kiểm soát tốt hơn với các công việc cần chuẩn bị và thực hiện theo luồng.  Để thực hiện công việc này, Adapter cung cấp một phương thức gọi là createStatement() cho phép ta tạo ra một Driver Statement cụ thể để sử dụng giúp ta có thể quản lý công việc cần chuẩn bị và thực hiện theo luồng (prepare-then-execute workflow) 18 Bài 4: Database và Model 3. Tạo Statement  Cú pháp: 19 $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute(); Bài 4: Database và Model Ví dụ: Liệt kê danh sách khách hàng  File model LienheTable public function listAll($adapter) { $sql='select * FROM Khachhang'; $statement = $adapter->createStatement($sql); $result = $statement->execute(); return $result; } 20 Bài 4: Database và Model  File controller public function indexAction() { $auth = new AuthenticationService(); if ($auth->hasIdentity()) { $lienheTable = new LienheTable(); $sm=$this->getServiceLocator(); $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $result = $lienheTable->listAll($dbAdapter); if($result->count()>0) { foreach ($result as $row) { echo $row['Hoten'] . ''; } } } } 21 Bài 4: Database và Model 22 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 1 LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 2 Bài 4: Database và Model 1. ZendDbAdapter 2. Chuẩn bị/ thực thi câu lệnh truy vấn 3. Tạo Statement 4. ZendDbSql 5. ZendDbTable Gateway 6. ZendDb RowGateway 7. Database 8. Model 9. Xây dựng phương thức trong Controller 10. Tạo view Bài 4: Database và Model 3 1. ZendDbAdapter Giới thiệu:  Đối tượng Adapter là một thành phần (sub-component) quan trọng nhất của Zend\Db. Nó chịu trách nhiệm thích ứng các code được viết trong Zend\Db tới các phần mở rộng PHP đích và cơ sở dữ liệu từ nhà cung cấp.  Để thực hiện việc này, nó tạo ra một lớp trừu tượng cho các thành phần mở rộng PHP, được gọi là "Driver" của Zend\Db adapter. Nó cũng tạo ra một lớp trừu tượng, được gọi là "Platform" của adapter, cho các nguồn khác nhau mà mỗi nhà cung cấp platform cụ thể có thể có trong việc thực hiện SQL / RDBMS. Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Tạo một adapter đơn giản bằng cách sử dụng lớp Zend\Db\Adapter\Adapter. Trường hợp phổ biến nhất là thông qua một mảng cấu hình cho Adapter.  Mảng này là một trừu tượng với các tham số yêu cầu ở mức mở rộng. 4 $adapter = new Zend\Db\Adapter\Adapter($configArray); Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Bảng dưới đây là các giá trị nên có trong mảng cấu hình: 5 Từ khóa Yêu cầu/ không yêu cầu phải có? Giá trị driver Yêu cầu Mysqli, Sqlsrv, Pdo_Sqlite, Pdo_Mysql, Pdo=OtherPdoDriver database Thường yêu cầu Tên của CSDL username Thường yêu cầu Tên đăng nhập khi kết nối password Thường yêu cầu Mật khẩu hostname Không thường yêu cầu Địa chỉ IP hoặc hostname kết nối tới port Không thường yêu cầu port charset Không thường yêu cầu Bộ ký tự sử dụng Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Ví dụ: Kết nối tới MySQL sử dụng ext/mysqli: 6 $adapter = new Zend\Db\Adapter\Adapter(array( 'driver' => 'Mysqli', 'database' => 'zend_db_example', 'username' => 'developer', 'password' => 'developer-password' )); Danh sách các Driver được hỗ trợ: •Mysqli: ext/mysqli driver •Pgsql: ext/pgsql driver •Sqlsrv: ext/sqlsrv driver (from Microsoft) •Pdo_Mysql: MySQL thông qua mở rộng PDO •Pdo_Sqlite: SQLite thông qua mở rộng PDO •Pdo_Pgsql: PostgreSQL thông qua mở rộng PDO Bài 4: Database và Model 1. ZendDbAdapter – tạo Adapter  Chú ý: – Sử dụng cách này để tạo adapter, lớp Adapter sẽ cố gắng để tạo ra bất kỳ phụ thuộc nào dù không được nêu rõ ràng. – Một đối tượng Driver sẽ được tạo ra từ mảng cấu hình được cung cấp trong constructor. Một đối tượng Platform sẽ được tạo ra dựa vào kiểu của lớp instantiated. – Một đối tượng mặc định ResultSet được tạo ra và sử dụng. Các đối tượng khác cũng có thể được thêm vào. 7 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Chuẩn bị câu lệnh truy vấn thông qua Zend\Db\Adapter\Adapter::query() – Mặc định, query() là thứ mà ta chuẩn bị sẵn và xem như một phương tiện để xử lý các câu lệnh SQL. Ta sẽ cung cấp một câu lệnh SQL với các giá trị được thay thế bằng các placeholder, các tham số. – Ví dụ về quy trình làm việc với Zend\Db\Adapter\Adapter này là: 8 $adapter->query('SELECT * FROM `artist` WHERE `id` = ?', array(5)); Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Ví dụ này được thực hiện thông qua các bước sau: – Tạo ra một đối tượng Statement mới – Chuẩn bị một mảng để truyền vào ParameterContainer nếu cần – Đưa ParameterContainer vào đối tượng Statement – Thực thi đối tượng Statement, tạo ra một đối tượng kết quả Result – Kiểm tra đối tượng Result để kiểm tra xem sql được cung cấp có phải là một “query” (lấy dữ liệu), hay là một bộ các statement được tạo ra (thêm, cập nhật hoăc xóa dữ liệu). – Nếu kết quả là một bộ câu lệnh truy vấn được tạo ra thì sao chép ResultSet prototype, đưa Result vào như nguồn dữ kiệu, trả về (trường hợp thêm, cập nhật hoặc xóa dữ liệu) – Ngược lại, trả về Result (trường hợp lấy dữ liệu để hiển thị) 9 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn  Thực thi câu lệnh truy vấn thông qua Zend\Db\Adapter\Adapter::query() – Trong một vài trường hợp ta cần phải thực thi ngay các statement. – Mục đích chính của việc thực thi ngay câu lệnh truy vấn thay vì phải chuẩn bị rồi mới thực thi là vì có thể ta đang cố gắng thực thi một DDL statement (trong hầu hết các extension và các vendor platform, mà không cần chuẩn bị. 10 Bài 4: Database và Model 2. Chuẩn bị/ thực thi câu lệnh truy vấn – Ví dụ: – Một khác biệt duy nhất cần chú ý là ta cần phải cung cấp Adapter::QUERY_MODE_EXECUTE (execute) là tham số thứ hai. 11 $adapter->query('ALTER TABLE ADD INDEX(`foo_index`) ON (`foo_column`)', Adapter::QUERY_MODE_EXECUTE); Bài 4: Database và Model 3. Tạo Statement  Trong khi query() rất hữu ích khi thực hiện truy vấn nhanh một lần tới CSDL thông qua Adapter, nó thường có ý nghĩa hơn khi tạo ra một statement và tương tác trực tiếp để ta có thể kiểm soát tốt hơn với các công việc cần chuẩn bị và thực hiện theo luồng.  Để thực hiện công việc này, Adapter cung cấp một phương thức gọi là createStatement() cho phép ta tạo ra một Driver Statement cụ thể để sử dụng giúp ta có thể quản lý công việc cần chuẩn bị và thực hiện theo luồng (prepare-then-execute workflow) 12 Bài 4: Database và Model 3. Tạo Statement  Cú pháp: 13 $statement = $adapter->createStatement($sql, $optionalParameters); $result = $statement->execute(); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql là một lớp SQL trừu tượng dùng để xây dựng các truy vấn SQL nền tảng, cụ thể thông qua object-oriented API.  Kết quả cuối cùng của đối tượng Zend\Db\Sql sẽ vừa tạo ra một Statement và Parameter container đại diện cho truy vấn đích, hoặc là một chuỗi đầy đủ có thể thực thi trực tiếp trên nền tảng của CSDL.  Để thực hiện việc này, các đối tượng Zend\Db\Sql cung cấp một đối tượng Zend\Db\Adapter\Adapter (đã giới thiệu ở phần trên) để tạo ra những kết quả mong muốn. 14 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Có một số công việc chính cần phải tương tác với CSDL (từ DML - Data Manipulation Language): truy vấn lọc dữ liệu, thêm dữ liệu, cập nhật và xóa dữ liệu. – Như vậy có bốn đối tượng chính mà developer cần tương tác hoặc xây dựng các câu lệnh truy vấn: Zend\Db\Sql\Select, Insert, Update và Delete. – Tuy nhiên bốn công việc này có liên quan khá mật thiết với nhau, và thường kết hợp cùng nhau trong cùng một ứng dụng, các đối tượng Zend\Db\Sql\Sql giúp ta tạo ra chúng và tạo ra kết quả mà ta mong muốn có được. 15 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql  Bây giờ developer có thể tương tác với những đối tượng này. 16 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); // @return Zend\Db\Sql\Select $insert = $sql->insert(); // @return Zend\Db\Sql\Insert $update = $sql->update(); // @return Zend\Db\Sql\Update $delete = $sql->delete(); // @return Zend\Db\Sql\Delete Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Sử dụng đối tượng Select – Chuẩn bị câu lệnh truy vấn Ví dụ: 17 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(array('id' => 2)); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Sử dụng đối tượng Select – Thực thi câu lệnh truy vấn Ví dụ: 18 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(array('id' => 2)); $selectString = $sql->getSqlStringForSqlObject($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Các đối tượng Zend\Db\Sql\Sql cũng có thể được ràng buộc tới một bảng cụ thể, do đó việc thực hiện đối tượng select, insert, update, hay delete, tất cả đều chủ yếu nằm trên cùng một bảng khi được tạo ra. – Ví dụ 19 use Zend\Db\Sql\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(array('id' => 2)); // $select đã có từ ('foo') Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select, Insert, Update và Delete – Mỗi đối tượng đều được triển khai từ (2) interface dưới đây: – Có nhiều phương thức ta có thể gọi để tạo ra (a) một statement được chuẩn bị sẵn, hoặc (b) một chuỗi để thực thi. 20 interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement); } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select – Zend\Db\Sql\Select là một đối tượng mà chức năng chính là để giới thiệu một API thống nhất cho việc xây dựng nền tảng cho các truy vấn SQL SELECT cụ thể. Lớp này có thể được nhanh chóng thực hiện mà không cần Zend\Db\Sql\Sql: – Nếu một bảng được cung cấp cho một đối tượng Select, thì phương thức from() không thể được gọi sau này để thay đổi tên của bảng. 21 use Zend\Db\Sql\Select; $select = new Select(); // hoặc tạo ra một $select cho một bảng cụ thể $select = new Select('foo'); Bài 4: Database và Model 4. ZendDbSql  Khi ta có một đối tượng Select hợp lệ, API có thể được sử dụng để tiếp tục xác định các phần khác nhau của select statement: – From: $select->from(‘$table'); – Columns: $select->columns(array $columns, $prefixColumnsWithTable = true); – Join: $select-> join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER); 22 Bài 4: Database và Model 4. ZendDbSql – Where/ having: $select->where($predicate, $combination = Predicate\PredicateSet::OP_AND); – Group: $select->group($group); – Having: $select->having($predicate, $combination = Predicate\PredicateSet::OP_AND); – Order: $select->order($order); – Limit: $select->limit($limit); – Offset: $select->offset($offset); 23 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - from 24 // như là một chuỗi: $select->from('foo'); // như là một mảng: // tạo ra SELECT "t".* FROM "table" AS "t" $select->from(array('t' => 'table')); // Sử dụng một Sql\TableIdentifier: // giống như output ở trên as above $select->from(new TableIdentifier(array('t' => 'table'))); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - columns() 25 // như là mảng các tên cột $select->columns(array('foo', 'bar')); // như là mảng kết hợp giữa khóa và giá trị: // tạo ra ‘bar' AS 'foo', 'bax' AS 'baz' $select->columns(array('foo' => 'bar', 'baz' => 'bax')); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - join() 26 $select->join( 'foo' // tên bảng, 'id = bar.id', // điều kiện kết, array('bar', 'baz'), // (tùy chọn) danh sách các cột tương ứng với biểu thức columns() phía trên $select::JOIN_OUTER // (tùy chọn), kết inner, outer, left, right ); $select->from(array('f' => 'foo')) // bảng cơ sở ->join(array('b' => 'bar'), // kết với một bảng khác 'f.foo_id = b.foo_id'); // điều kiện kết Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - where() 27 // SELECT "foo".* FROM "foo" WHERE x = 5 $select->from('foo')->where('x = 5'); // SELECT "foo".* FROM "foo" WHERE x = 5 AND y = z $select->from('foo')->where(array('x = 5', 'y = z')); // SELECT "foo".* FROM "foo" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL $select->from('foo')->where(array( 'c1' => null, 'c2' => array(1, 2, 3), new \Zend\Db\Sql\Predicate\IsNotNull('c3') )); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - order() 28 $select = new Select; $select->order('id DESC'); // produces 'id' DESC $select = new Select; $select->order('id DESC') ->order('name ASC, age DESC'); // produces 'id' DESC, 'name' ASC, 'age' DESC $select = new Select; $select->order(array('name ASC', 'age DESC')); // produces 'name' ASC, 'age' DESC Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - limit() và offset() 29 $select = new Select; $select->limit(5); // always takes an integer/numeric $select->offset(10); // similarly takes an integer/numeric Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: API 30 class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct($table = null); public function into($table); public function columns(array $columns); public function values(array $values, $flag = self::VALUES_SET); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: columns() 31 $insert->columns(array('foo', 'bar')); // set the valid columns Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: values() 32 // default behavior of values is to set the values // succesive calls will not preserve values from previous calls $insert->values(array( 'col_1' => 'value1', 'col_2' => 'value2' )); / /merging values with previous calls $insert->values(array('col_2' => 'value2'), $insert::VALUES); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Update: 33 class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct($table = null); public function table($table); public function set(array $values, $flag = self::VALUES_SET); public function where($predicate, $combination = Predicate\PredicateSet::OP_AND); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Update – set() 34 $update->set(array('foo' => 'bar', 'baz' => 'bax')); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Delete 35 class Delete { public $where; // @param Where $where public function __construct($table = null); public function from($table); public function where($predicate, $combination = Predicate\PredicateSet::OP_AND); } Bài 4: Database và Model 5. ZendDbTable Gateway  Đối tượng Table Gateway được dùng để cung cấp một đối tượng đại diện cho một bảng trong CSDL, và các phương thức của đối tượng này ánh xạ đến những thao tác tương tự như trong bảng của CSDL. Interface của đối tượng này có nội dung như sau: 36 interface Zend\Db\TableGateway\TableGatewayInterface { public function getTable(); public function select($where = null); public function insert($set); public function update($set, $where = null); public function delete($where); } Bài 4: Database và Model 5. ZendDbTable Gateway  Có hai implementation chính của TableGatewayInterface hiệu quả nhất là: AbstractTableGateway và TableGateway.  AbstractTableGateway là một implementation cơ sở trừu tượng cung cấp các chức năng như select(), insert(), update(), delete() thưc hiện các công việc tương tự như các đối tượng SQL object, và các phương thức selectWith(), insertWith(), updateWith() và deleteWith() 37 Bài 4: Database và Model 5. ZendDbTable Gateway  Hơn thế, AbstractTableGateway cũng thực hiện như một “Feature” API, cho phép mở rộng các hành vi – behavior của TableGateway implementation cơ sở mà không cần phải mở rộng lớp với các tính năng mới.  TableGateway cụ thể đơn giản chỉ cần thêm một constructor hợp lý cho AbstractTableGateway class, TableGateway không cần phải được mở rộng để tiêu thụ và sử dụng để phát huy tối đa. 38 Bài 4: Database và Model 5. ZendDbTable Gateway  Sử dụng: Cách nhanh chóng để có thể dùng Zend\Db\TableGateway là cấu hình và sử dụng impelemtation cụ thể của TableGateway. API của một TableGateway cụ thể là: 39 Bài 4: Database và Model 40 class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function __construct($table, Adapter $adapter, $features = null, ResultSet $resultSetPrototype = null, Sql $sql = null) /** Inherited from AbstractTableGateway */ public function isInitialized(); public function initialize(); public function getTable(); public function getAdapter(); public function getColumns(); public function getFeatureSet(); public function getResultSetPrototype(); public function getSql(); public function select($where = null); public function selectWith(Select $select); public function insert($set); public function insertWith(Insert $insert); public function update($set, $where = null); public function updateWith(Update $update); public function delete($where); public function deleteWith(Delete $delete); public function getLastInsertValue(); } Bài 4: Database và Model 5. ZendDbTable Gateway  Sử dụng: – Đối tượng TableGateway cụ thể được khởi tạo ở hàm khỏi tạo. Tên bảng và instance của một Adapter cần thiết để thiết lập một đối tượng làm việc TableGateway. – Khi phương thức select() được thực thi, một đối tượng ResultSet đơn giản với một Adapter’s Result sẽ được trả về và sẵn sàng cho việc sử dụng. 41 Bài 4: Database và Model 5. ZendDbTable Gateway  Sử dụng: – Ví dụ: 42 use Zend\Db\TableGateway\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(array('type' => 'PHP')); echo 'Projects of type PHP: '; foreach ($rowset as $projectRow) { echo $projectRow['name'] . PHP_EOL; } // or, when expecting a single row: $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(array('id' => 2)); $artistRow = $rowset->current(); var_dump($artistRow); Bài 4: Database và Model 5. ZendDbTable Gateway  Sử dụng: – Phương thức select() có những lập luận tương tự như Zend\Db\Sql\Select::where() với việc bổ sung cũng được chấp nhận, sẽ thông qua đối tượng Select được sử dụng để xây dựng truy vấn SELECT. 43 use Zend\Db\TableGateway\TableGateway; use Zend\Db\Sql\Select; $artistTable = new TableGateway('artist', $adapter); // search for at most 2 artists who's name starts with Brit, ascending $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); $select->order('name ASC')->limit(2); }); Bài 4: Database và Model 5. ZendDbTable Gateway  Đặc điểm của Table Gateway – Features API cho phép mở rộng chức năng của đối tượng TableGateway cơ sở mà không cần phải mở rộng lớp cơ sở. – Với đối tượng TableGateway, đặc tính cần phải được đưa vào thông qua constructor. – Constructor có thể lấy Features trong ba dạng form khác nhau: single feature object, FeatureSet object, hoặc mảng các Feature object. 44 Bài 4: Database và Model 5. ZendDbTable Gateway – Dưới đây là một số feature built-in và shipped với Zend\Db: • GlobalAdapterFeature: khả năng sử dụng global/static adapter mà không cần phải đưa nó vào một TableGateway instance. Nó rất hữu dụng khi ta mở rộng việc sử dụng AbstractTableGateway: 45 class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\FeatureSet(); $this->featureSet->addFeature(new Feature\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code, in a bootstrap Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statially loaded Bài 4: Database và Model 5. ZendDbTable Gateway – Dưới đây là một số feature built-in và shipped với Zend\Db: • MasterSlaveFeature: khả năng sử dụng master adapter để insert(), update(), và delete() khi dùng slave adapter cho tất cả các select() operation (toán tử/ hoạt động). 46 $table = new TableGateway('artist', $adapter, new Feature\MasterSlaveFeature($slaveAdapter)); Bài 4: Database và Model 5. ZendDbTable Gateway – Dưới đây là một số feature built-in và shipped với Zend\Db: • MetadataFeature: khả năng populate TableGateway với thông tin của cột lấy từ đối tượng Metadata. Nó cũng sẽ lưu trữ thông tin khóa chính trong trường hợp RowGatewayFeature cần sử dụng thông tin này. 47 $table = new TableGateway('artist', $adapter, new Feature\MeatadataFeature()); Bài 4: Database và Model 5. ZendDbTable Gateway – Dưới đây là một số feature built-in và shipped với Zend\Db: • EventFeature: khả năng sử dụng đối tượng TableGateway với Zend\EventManager và để có thể đăng ký vào các sự kiện khác nhau trong một vòng đời của TableGateway. 48 $table = new TableGateway('artist', $adapter, new Feature\EventFeature($eventManagerInstance)); Bài 4: Database và Model 5. ZendDbTable Gateway – Dưới đây là một số feature built-in và shipped với Zend\Db: • RowGatewayFeature: khả năng cho select() trả về đối tượng ResultSet object lặp lại khi cần: 49 $table = new TableGateway('artist', $adapter, new Feature\RowGatewayFeature('id')); $results = $table->select(array('id' => 2)); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); Bài 4: Database và Model 6. ZendDb RowGateway  Zend\Db\RowGateway là một component con của Zend\Db thực hiện mẫu Row Gateway từ PoEAA.  Các đối tượng Row Gateway có mẫu là một hàng trong CSDL và có những phương thức như save() và delete() giúp duy trì dòng này như một đối tượng trong CSDL.  Tương tự, sau khi một dòng từ CSDL được lấy ra, thao tác và save() trở lại CSDL ở đúng vị trí cũ, hoặc nó cũng có thể bị xóa từ bảng. 50 Bài 4: Database và Model 6. ZendDb RowGateway  Interface cho một đối tượng Row Gateway đơn giản chỉ cần thêm vào phương thức save() và delete và đây là một interface cần được giả định khi một component có một phụ thuộc dự kiến sẽ là một thể hiện của đối tượng RowGateway: 51 interface RowGatewayInterface { public function save(); public function delete(); } Bài 4: Database và Model 6. ZendDb RowGateway  Sử dụng: – Hầu hết thời gian, RowGateway được sử dụng kết hợp với các đối tượng Zend\Db\ResultSet khác, cũng có thể sử dụng chúng độc lập. – Và để sử dụng chúng một cách độc lập đơn giản ta chỉ cần một Adapter và một bộ dữ liệu đi cùng. 52 Bài 4: Database và Model 6. ZendDb RowGateway  Sử dụng: – Zend\Db\RowGateway\RowGateway trình bày ở dạng đơn giản của nó: 53 use Zend\Db\RowGateway\RowGateway; // query the database $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', array(2)); // get array of data $rowData = $resultSet->current()->getArrayCopy(); // row gateway $rowGateway = new RowGateway('id', 'my_table', $adapter); $rowGateway->populate($rowData); $rowGateway->first_name = 'New Name'; $rowGateway->save(); // or delete this row: $rowGateway->delete(); Bài 4: Database và Model 6. ZendDb RowGateway – Luồng công việc được mô tả phía trên rất đơn giản khi RowGateway được sử dụng kết hợp với TableGateway feature. Kết quả đạt được là một đối tượng Table Gateway khi dùng select() từ một bảng, nó sẽ tạo ra một ResultSet mà sau đó có khả năng tạo ra một đối tượng Row Gateway hợp lệ: 54 use Zend\Db\TableGateway\Feature\RowGatewayFeature; use Zend\Db\TableGateway\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(array('id' => 2)); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); Bài 4: Database và Model 7. Database  Sau khi đã thiết lập các phương thức cần thiết cho controller của module Product và tạo các view script chưa có nội dung, chúng ta cần phải xây dựng model cho ứng dụng.  Model là thành phần quan trọng của ứng dụng, nó liên quan tới CSDL. Trong ZF2, chúng ta sử dụng lớp Zend\Db\TableGateway\TableGateway để tìm kiếm, thêm, cập nhật và xóa các dòng ra khỏi CSDL.  Sử dụng MySQL, thông qua PHP’s PDO driver, để tạo một CSDL cho ứng dụng. 55 Bài 4: Database và Model 7. Database  Thực hiện – Ví dụ: tạo một CSDL có tên là “zend_app” có cấu trúc như sau: – Sau đó thêm vào một số dòng dữ liệu cần thiết: 56 Bài 4: Database và Model 8. Models  Zend Framework không cung cấp sẵn Zend\Model component như model trong business logic, nó phụ thuộc vào quyết định của chúng ta muốn nó thực hiện công việc gì. Có khá nhiều component chúng ta có thể sử dụng khi cần.  Một cách tiếp cận là chúng ta có các lớp model tương ứng với các thực thể của ứng dụng, sau đó sử dụng các mapper objects để load và lưu các thực thể bào CSDL.  Một cách tiếp cận khác là sử dụng một ORM như Doctrine hay Propel. 57 Bài 4: Database và Model 8. Models  Trong bài này chúng ta tạo ra một model đơn giản bằng cách tạo ra ProductTable class sử dụng Zend\Db\TableGateway\TableGateway class, trong đó mội đối tượng Product là một Product object (được biết như là một thực thể - entity).  Model này là một implementation của Table Data Gateway design pattern, nó cho phép tương tác với dữ liệu trong bảng 58 Bài 4: Database và Model 8. Models  Thực hiện – Bước 1: Xây dựng lớp thực thể Product trong thư mục Model: 59 // module/Product/src/Product/Model/Product.php: namespace Product\Model; class Product { public $id; public $name; public $price; public $image public function exchangeArray($data) { $this->id = (isset($data['id'])) ? $data['id'] : null; $this->name = (isset($data['name'])) ? $data['name'] : null; $this->price = (isset($data['price'])) ? $data['price'] : null; $this->image = (isset($data['image'])) ? $data['image'] : null; } } Bài 4: Database và Model 8. Models  Thực hiện – Đối tượng thực thể Product là một class PHP đơn giản. Để có thể làm việc với Zend\Db’s TableGateway class, chúng ta cần phải implement phương thức exchangeArray(). – Phương thức này sẽ chép dữ liệu từ mảng tới các thuộc tính cùa thực thể. 60 Bài 4: Database và Model 8. Models  Thực hiện – Bước 2: Tiếp theo, cần phải tạo Table Class trong thư mục Model của module – ProductTable. ProductTable sẽ có các phương thức cần thiết cho việc thực hiện các action khai báo trong controller phía trên: • Đặt một biến protected tên là $tableGateway được gán giá trị truyền vào từ controller trong phương thức khởi tạo cùa constructor. Chúng ta sẽ sử dụng nó để thực hiện các chức năng trong bảng dữ liệu tới Products • Chúng ta tạo ra các phương thức mà ứng dụng sẽ sử dụng để interface với table gateway. 61 Bài 4: Database và Model 8. Models – Phương thức fetchAll() nhận tất cả các dòng của bảng Products từ CSDL và xem như là một ResultSet – Phương thức getProduct() nhận một dòng, là một đối tượng Product – Phương thức saveProduct() vừa tạo một dòng mới vào CSDL vừa cập nhật dòng đã tồn tại trong bảng của CSDL – Phương thức deleteProduct() xóa một dòng trong bảng. 62 Bài 4: Database và Model 8. Models  Thực hiện 63 namespace Product\Model; use Zend\Db\TableGateway\TableGateway; class ProductTable { protected $tableGateway; public function __construct(TableGateway $tableGateway) { $this->tableGateway = $tableGateway; } public function fetchAll() { $resultSet = $this->tableGateway->select(); return $resultSet; } Bài 4: Database và Model 64 // continue public function getProduct($id) { $id = (int) $id; $rowset = $this->tableGateway->select(array('id' => $id)); $row = $rowset->current(); if (!$row) { throw new \Exception("Could not find row $id"); } return $row; } // continue public function deleteProduct($id) { $this->tableGateway->delete(array('id' => $id)); } } Bài 4: Database và Model 65 // continue public function saveProduct(Product $product) { $data = array( 'name' => $product->name, 'price' => $product->price, ‘image' => $product->image, ); $id = (int)$product->id; if ($id == 0) { $this->tableGateway->insert($data); } else { if ($this->getProduct($id)) { $this->tableGateway->update($data, array('id' => $id)); } else { throw new \Exception('Form id does not exist'); } } } Bài 4: Database và Model 8. Models  Thực hiện – Bước 3: Sử dụng ServiceManager để cấu hình table gateway đưa vào ProductTable • Để thường xuyên sử dụng cùng một instance của ProductTable, chúng ta sẽ dùng ServiceManager để định nghĩa cách tạo ra nó. • Việc này được thực hiện trong lớp Module, nơi chúng ta tạo ra phương thức ServiceConfig(), nó được gọi tự động bằng ModuleManager và áp dụng cho ServiceManager. • Chúng ta có thể nhận nó trong controller khi chúng ta cần đến. 66 Bài 4: Database và Model 8. Models  Thực hiện – Bước 3: Sử dụng ServiceManager để cấu hình table gateway đưa vào ProductTable • Để cấu hình ServiceManager, chúng ta cung cấp tên của lớp (to be instantiated or a factory (closure or callback) that instantiates the object) khi ServiceManager. • Chúng ta thực hiện phương thức getServiceConfig() để cung cấp một factory mà tạo ra ProductTable. Thêm phương thức này vào cuối Module class. 67 Bài 4: Database và Model 68 // module/Product/Module.php: namespace Product; use Product\Model\Product; use Product\Model\ProductTable; use Zend\Db\ResultSet\ResultSet; use Zend\Db\TableGateway\TableGateway; class Module { // getAutoloaderConfig() and getConfig() methods here // Add this method: public function getServiceConfig() { return array('factories' => array( 'Product\Model\ProductTable' => function($sm) { $tableGateway = $sm->get('ProductTableGateway'); $table = new ProductTable($tableGateway); return $table; }, 'ProductTableGateway' => function ($sm) { $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Product()); return new TableGateway('product', $dbAdapter, null, $resultSetPrototype); },),);} } Bài 4: Database và Model 8. Models  Thực hiện – Bước 3: • Phương thức này trả về một mảng các factory được kết hợp với nhau bởi ModuleManager trước khi chuyển tới ServiceManager. • Factory dành cho Product\Model\ProductTable sử dụng ServiceManager để tạo một ProductTableGateway để chuyển tới ProductTable. • Chúng ta cũng cho ServiceManager biết rằng ProductTableGateway được tạo ra bằng cách lấy một Zend\Db\Adapter\Adapter (cũng từ ServiceManager) và sử dụng nó để tạo ra một TableGateway object. • TableGateway sử dụng Product object khi nó tạo ra một dòng kết quả mới. TableGateway classes sử dụng prototype pattern cho việc tạo ra bộ kết quả và thực thể. 69 Bài 4: Database và Model 8. Models  Thực hiện – Bước 4: Cuối cùng, cần phải cấu hình ServiceManager • Để ServiceManager biết cách lấy Zend\Db\Adapter\Adapter bằng cách dùng một tên là Zend\Db\Adapter\AdapterServiceFactory mà chúng ta có thể cấu hình trong hệ thống cầu hình kết hợp. • ModuleManager của ZF2 tổng hợp các cấu hình từ mỗi file module.config.php của module sau đó đưa vào các file trong thư mục config/autoload (*.global.php và *.local.php). • Chúng ta sẽ thêm thông tin cấu hình CSDL vào file global.php. Ta cũng có thể dùng local.php (bên ngoài VCS) để lưu trữ thông tin cho CSDL nếu chúng ta muốn: 70 Bài 4: Database và Model  global.php 71 return array( 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=zend_app;host=localhost', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory', ), ), ); Bài 4: Database và Model  local.php 72 // config/autoload/local.php: return array( 'db' => array( 'username' => 'YOUR USERNAME HERE', 'password' => 'YOUR PASSWORD HERE', ), ); Bài 4: Database và Model 9. Xây dựng phương thức trong Controller  Sau khi xây dựng các phương thức cần thiết trong Model cho Product, ta quay lại Controller để xây dựng action cho Product 73 Bài 4: Database và Model 9. Xây dựng phương thức trong Controller  Thực hiện  Ta thêm vào biến protected sau đây ở dòng đầu của class: 74 // module/Product/src/Product/Controller/ProductController.php: public function getProductTable() { if (!$this->productTable) { $sm = $this->getServiceLocator(); $this->productTable = $sm->get('Product\Model\ProductTable'); } return $this->productTable; } protected $productTable; Bài 4: Database và Model 9. Xây dựng phương thức trong Controller  Thực hiện – Bây giờ chúng ta có thể gọi phương thức getProductTable() trong controller ở nơi mà chúng ta muốn tương tác tới model. – Để kiểm tra chúng ta có thể thêm một test vào ProductControllerTest class: – Nếu vị trí của service được cấu hình chính xác trong tập tin Module.php thí chúng ta sẽ có một instance của Product\Model\ProductTable khi gọi phương thức getProductTable() 75 public function testGetProductTableReturnsAnInstanceOfProductTable() { $this->assertInstanceOf('Product\Model\ProductTable', $this->controller- >getProductTable()); } Bài 4: Database và Model 9. Xây dựng phương thức trong Controller  Thực hiện: – Ví dụ: Lấy danh mục sản phẩm tranh • Để hiển thị, chúng ta cần phải lấy danh mục sản phẩm tranh từ model sau đó chuyển nó sang view bằng cách hoàn thành phương thức indexAction() đã được tạo ra ở trên trong lớp ProductController bằng cách điền nội dung vào như sau: 76 // module/Product/src/Product/Controller/ProductController.php: public function indexAction() { return new ViewModel(array( 'products' => $this->getProductTable()->fetchAll(), )); } Bài 4: Database và Model 10. Tạo View  Sau khi đã có model và controller, công việc cuối cùng là tạo view để hiển thị. – Thực hiện: hiển thị danh mục sản phẩm tranh • Trong ZF2, để có thể đặt các biến trong view, ta cần phải trả về một ViewModel instance với tham số đầu tiên của constructor là một mảng chứa dữ liệu cần hiển thị. • Mảng dữ liệu này sẽ được tự động chuyển sang view. • ViewModel object cũng cho phép chúng ta thay đổi view Script cần sử dụng, nhưng mặc định ta dùng {controller name}/{action name}. 77 Bài 4: Database và Model 10. Tạo View  Sau khi đã có model và controller, công việc cuối cùng là tạo view để hiển thị. – Thực hiện: hiển thị danh mục sản phẩm tranh • Trong ZF2, để có thể đặt các biến trong view, ta cần phải trả về một ViewModel instance với tham số đầu tiên của constructor là một mảng chứa dữ liệu cần hiển thị. • Mảng dữ liệu này sẽ được tự động chuyển sang view. • ViewModel object cũng cho phép chúng ta thay đổi view Script cần sử dụng, nhưng mặc định ta dùng {controller name}/{action name}. 78 Bài 4: Database và Model 79 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 1 LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM 2 Bài 4: Database và Model Phần SQL Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql là một lớp SQL trừu tượng dùng để xây dựng các truy vấn SQL nền tảng, cụ thể thông qua object-oriented API.  Kết quả cuối cùng của đối tượng Zend\Db\Sql sẽ vừa tạo ra một Statement và Parameter container đại diện cho truy vấn đích, hoặc là một chuỗi đầy đủ có thể thực thi trực tiếp trên nền tảng của CSDL.  Để thực hiện việc này, các đối tượng Zend\Db\Sql cung cấp một đối tượng Zend\Db\Adapter\Adapter (đã giới thiệu ở phần trên) để tạo ra những kết quả mong muốn. 3 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Có một số công việc chính cần phải tương tác với CSDL (từ DML - Data Manipulation Language): truy vấn lọc dữ liệu, thêm dữ liệu, cập nhật và xóa dữ liệu. – Như vậy có bốn đối tượng chính mà developer cần tương tác hoặc xây dựng các câu lệnh truy vấn: Zend\Db\Sql\Select, Insert, Update và Delete. – Tuy nhiên bốn công việc này có liên quan khá mật thiết với nhau, và thường kết hợp cùng nhau trong cùng một ứng dụng, các đối tượng Zend\Db\Sql\Sql giúp ta tạo ra chúng và tạo ra kết quả mà ta mong muốn có được. 4 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql  Bây giờ developer có thể tương tác với những đối tượng này. 5 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); // @return Zend\Db\Sql\Select $insert = $sql->insert(); // @return Zend\Db\Sql\Insert $update = $sql->update(); // @return Zend\Db\Sql\Update $delete = $sql->delete(); // @return Zend\Db\Sql\Delete Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Sử dụng đối tượng Select – Chuẩn bị câu lệnh truy vấn Ví dụ: 6 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(array('id' => 2)); $statement = $sql->prepareStatementForSqlObject($select); $results = $statement->execute(); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Sử dụng đối tượng Select – Thực thi câu lệnh truy vấn Ví dụ: 7 use Zend\Db\Sql\Sql; $sql = new Sql($adapter); $select = $sql->select(); $select->from('foo'); $select->where(array('id' => 2)); $selectString = $sql->getSqlStringForSqlObject($select); $results = $adapter->query($selectString, $adapter::QUERY_MODE_EXECUTE); Bài 4: Database và Model 4. ZendDbSql Ví dụ: Liệt kê danh sách bài viết File controller BaivietController public function indexAction() { $this->layout()->setTemplate('layout/layout_admin'); $sm=$this->getServiceLocator(); $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $baivietTable = new BaivietTable('baiviet'); $dsBaiviet = $baivietTable->fetchAll($dbAdapter); return new ViewModel(array('baiviet'=>$dsBaiviet)); } 8 Bài 4: Database và Model 4. ZendDbSql File model BaivietTable public function fetchAll($dbadapter) { $sql = new Sql($dbadapter); $select=$sql->select('baiviet'); $state=$sql->prepareStatementForSqlObject($select); $results=$state->execute(); return $results; } 9 Bài 4: Database và Model 4. ZendDbSql File view Mã bài viếtTiêu đềNội dung tóm tắt  <?php $i=0; foreach($baiviet as $row) { if($i%2==0) echo ''; else echo ''; echo ''. $row['ma_bai_viet']. ''; echo 'url('Baiviet',array('action'=>'edit','id'=>$row['ma_bai_viet'])).'">' . $row['tieu_de'].''; echo''.$row['noi_dung_tom_tat'].'<a href="'.$this- >url('Baiviet',array('action'=>'delete','id'=>$row['ma_bai_viet'])).'">Xóa'; $i++; } ?> 10 Bài 4: Database và Model 4. ZendDbSql  Kết quả 11 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql – Các đối tượng Zend\Db\Sql\Sql cũng có thể được ràng buộc tới một bảng cụ thể, do đó việc thực hiện đối tượng select, insert, update, hay delete, tất cả đều chủ yếu nằm trên cùng một bảng khi được tạo ra. – Ví dụ 12 use Zend\Db\Sql\Sql; $sql = new Sql($adapter, 'foo'); $select = $sql->select(); $select->where(array('id' => 2)); // $select đã có từ ('foo') Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select, Insert, Update và Delete – Mỗi đối tượng đều được triển khai từ (2) interface dưới đây: – Có nhiều phương thức ta có thể gọi để tạo ra (a) một statement được chuẩn bị sẵn, hoặc (b) một chuỗi để thực thi. 13 interface PreparableSqlInterface { public function prepareStatement(Adapter $adapter, StatementInterface $statement); } interface SqlInterface { public function getSqlString(PlatformInterface $adapterPlatform = null); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select – Zend\Db\Sql\Select là một đối tượng mà chức năng chính là để giới thiệu một API thống nhất cho việc xây dựng nền tảng cho các truy vấn SQL SELECT cụ thể. Lớp này có thể được nhanh chóng thực hiện mà không cần Zend\Db\Sql\Sql: – Nếu một bảng được cung cấp cho một đối tượng Select, thì phương thức from() không thể được gọi sau này để thay đổi tên của bảng. 14 use Zend\Db\Sql\Select; $select = new Select(); // hoặc tạo ra một $select cho một bảng cụ thể $select = new Select('foo'); Bài 4: Database và Model 4. ZendDbSql  Khi ta có một đối tượng Select hợp lệ, API có thể được sử dụng để tiếp tục xác định các phần khác nhau của select statement: – From: $select->from(‘$table'); – Columns: $select->columns(array $columns, $prefixColumnsWithTable = true); – Join: $select-> join($name, $on, $columns = self::SQL_STAR, $type = self::JOIN_INNER); $select->join( 'users', 'id=baiviet.ma_nguoi_dung‘, array('fullname'), $select::JOIN_INNER); 15 Bài 4: Database và Model 4. ZendDbSql – Where/ having: $select->where($predicate, $combination = Predicate\PredicateSet::OP_AND); – Group: $select->group($group); – Having: $select->having($predicate, $combination = Predicate\PredicateSet::OP_AND); – Order: $select->order($order); – Limit: $select->limit($limit); – Offset: $select->offset($offset); 16 Bài 4: Database và Model 4. ZendDbSql 17 namespace Product\Model; use Zend\Db\Sql\Sql; use Zend\Db\Adapter\Adapter; Use Zend\Db\Sql\Expression; class ProductTable { public function fetchAll() { $adapter = new Adapter( array( 'driver'=>'Mysqli‘, 'database'=>'fashion', 'username'=>'root', 'password'=>'', ) ); $sql =new Sql($adapter); $select =$sql->select(); $select ->from('detail_bill'); $select ->columns(array('bill_id','tssp'=>new Expression('count(\'product_id\')'))); $select ->group(array('bill_id')); $select ->having(array('tssp>2')); $select ->limit(3); //Lay bao nhieu $select ->offset(0); //Lay tu $selectString=$sql->getSqlStringForSqlObject($select); $results=$adapter->query($selectString,$adapter::QUERY_MODE_EXECUTE); return $results; } } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - from 18 // như là một chuỗi: $select->from('foo'); // như là một mảng: // tạo ra SELECT "t".* FROM "table" AS "t" $select->from(array('t' => 'table')); // Sử dụng một Sql\TableIdentifier: // giống như output ở trên as above $select->from(new TableIdentifier(array('t' => 'table'))); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - columns() 19 // như là mảng các tên cột $select->columns(array('foo', 'bar')); // như là mảng kết hợp giữa khóa và giá trị: // tạo ra ‘bar' AS 'foo', 'bax' AS 'baz' $select->columns(array('foo' => 'bar', 'baz' => 'bax')); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - join() 20 $select->join( 'foo' // tên bảng, 'id = bar.id', // điều kiện kết, array('bar', 'baz'), // (tùy chọn) danh sách các cột tương ứng với biểu thức columns() phía trên $select::JOIN_OUTER // (tùy chọn), kết inner, outer, left, right ); $select->from(array('f' => 'foo')) // bảng cơ sở ->join(array('b' => 'bar'), // kết với một bảng khác 'f.foo_id = b.foo_id'); // điều kiện kết Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - where() 21 // SELECT "foo".* FROM "foo" WHERE x = 5 $select->from('foo')->where('x = 5'); // SELECT "foo".* FROM "foo" WHERE x = 5 AND y = z $select->from('foo')->where(array('x = 5', 'y = z')); // SELECT "foo".* FROM "foo" WHERE "c1" IS NULL AND "c2" IN (?, ?, ?) AND "c3" IS NOT NULL $select->from('foo')->where(array( 'c1' => null, 'c2' => array(1, 2, 3), new \Zend\Db\Sql\Predicate\IsNotNull('c3') )); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - order() 22 $select = new Select; $select->order('id DESC'); // produces 'id' DESC $select = new Select; $select->order('id DESC') ->order('name ASC, age DESC'); // produces 'id' DESC, 'name' ASC, 'age' DESC $select = new Select; $select->order(array('name ASC', 'age DESC')); // produces 'name' ASC, 'age' DESC Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Sql: Select - limit() và offset() 23 $select = new Select; $select->limit(5); // always takes an integer/numeric $select->offset(10); // similarly takes an integer/numeric Bài 4: Database và Model 4. ZendDbSql Ví dụ: Lấy thông tin một bài viết File controller  public function editAction()  {  $this->layout()->setTemplate('layout/layout_admin');  $sm=$this->getServiceLocator();  $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');  $baivietTable = new BaivietTable('baiviet');  $id=(int)$this->params()->fromRoute('id',0);  $baiviet = $baivietTable->getBaiviet($dbAdapter, $id);  return new ViewModel(array('baiviet'=>$baiviet));  } 24 Bài 4: Database và Model 4. ZendDbSql File BaivietModel  public function getBaiviet($dbadapter,$id)  {  $sql = new Sql($dbadapter);  $select=$sql->select();  $select->from('baiviet');  $select->columns(array('ma_bai_viet','tieu_de','noi_dung_tom_tat'));   $select->join('users','id=baiviet.ma_nguoi_dung',  array('fullname'),$select::JOIN_INNER);  $select->where(array('baiviet.ma_bai_viet'=>$id));   $state=$sql->prepareStatementForSqlObject($select);  $results=$state->execute();  return $results->current();  } 25 Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: API 26 class Insert implements SqlInterface, PreparableSqlInterface { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public function __construct($table = null); public function into($table); public function columns(array $columns); public function values(array $values, $flag = self::VALUES_SET); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: columns() 27 $insert->columns(array('foo', 'bar')); // set the valid columns Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Insert: values() 28 // default behavior of values is to set the values // succesive calls will not preserve values from previous calls $insert->values(array( 'col_1' => 'value1', 'col_2' => 'value2' )); / /merging values with previous calls $insert->values(array('col_2' => 'value2'), $insert::VALUES); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Update: 29 class Update { const VALUES_MERGE = 'merge'; const VALUES_SET = 'set'; public $where; // @param Where $where public function __construct($table = null); public function table($table); public function set(array $values, $flag = self::VALUES_SET); public function where($predicate, $combination = Predicate\PredicateSet::OP_AND); } Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Update – set() 30 $update->set(array('foo' => 'bar', 'baz' => 'bax')); Bài 4: Database và Model 4. ZendDbSql  Zend\Db\Sql\Delete 31 class Delete { public $where; // @param Where $where public function __construct($table = null); public function from($table); public function where($predicate, $combination = Predicate\PredicateSet::OP_AND); } Bài 4: Database và Model 32 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM LẬP TRÌNH PHP NÂNG CAO ZEND FRAMEWORK 2 1 TRUNG TÂM TIN HỌC ĐẠI HỌC KHOA HỌC TỰ NHIÊN-TP.HCM Bài 4: Database và Model 1. ZendDbAdapter 2. Chuẩn bị/ thực thi câu lệnh truy vấn 3. Tạo Statement 4. ZendDbSql 5. ZendDbTable Gateway 6. ZendDb RowGateway 7 D t b. a a ase 8. Model 9 Xây dựng phương thức trong Controller 2 . 10. Tạo view Bài 4: Database và Model 5 ZendDbTable Gateway.  Đối tượng Table Gateway được dùng để cung cấp một đối t đ i diệ h ột bả t CSDL à á ượng ạ n c o m ng rong , v c c phương thức của đối tượng này ánh xạ đến những thao tác tương tự như trong bảng của CSDL. Interface của đối tượng này có nội dung như sau: interface Zend\Db\TableGateway\TableGatewayInterface { public function getTable(); public function select($where = null); $public function insert( set); public function update($set, $where = null); public function delete($where); } 3 Bài 4: Database và Model 5 ZendDbTable Gateway.  Có hai implementation chính của TableGatewayInterface hiệ ả hất là Ab t tT bl G t àu qu n : s rac a e a eway v TableGateway.  AbstractTableGateway là một implementation cơ sở trừu tượng cung cấp các chức năng như select(), insert(), update(), delete() thưc hiện các công việc tương tự như các đối tượng SQL object và các phương thức , selectWith(), insertWith(), updateWith() và deleteWith() 4 Bài 4: Database và Model 5 ZendDbTable Gateway.  Hơn thế, AbstractTableGateway cũng thực hiện như một “F t ” API h hé ở ộ á hà h i b h iea ure , c o p p m r ng c c n v – e av or của TableGateway implementation cơ sở mà không cần phải mở rộng lớp với các tính năng mới.  TableGateway cụ thể đơn giản chỉ cần thêm một constructor hợp lý cho AbstractTableGateway class, TableGateway không cần phải được mở rộng để tiêu thụ và sử dụng để phát huy tối đa. 5 Bài 4: Database và Model 5 ZendDbTable Gateway.  Sử dụng: Cách nhanh chóng để có thể dùng Z d\Db\T bl G t là ấ hì h à ử den a e a eway c u n v s ụng impelemtation cụ thể của TableGateway. API của một TableGateway cụ thể là: 6 Bài 4: Database và Model class TableGateway extends AbstractTableGateway { public $lastInsertValue; public $table; public $adapter; public function construct($table, Adapter $adapter, $features = null, ResultSet __ $resultSetPrototype = null, Sql $sql = null) /** Inherited from AbstractTableGateway */ public function isInitialized(); public function initialize(); public function getTable(); public function getAdapter(); public function getColumns(); public function getFeatureSet(); public function getResultSetPrototype(); public function getSql(); public function select($where = null); public function selectWith(Select $select); public function insert($set); public function insertWith(Insert $insert); public function update($set, $where = null); public function updateWith(Update $update); 7 public function delete($where); public function deleteWith(Delete $delete); public function getLastInsertValue(); } Bài 4: Database và Model 5 ZendDbTable Gateway.  Sử dụng: – Đối tượng TableGateway cụ thể được khởi tạo ở hàm khỏi tạo. Tên bảng và instance của một Adapter cần thiết để thiết lập một đối tượng làm việc TableGateway. – Khi phương thức select() được thực thi, một đối tượng ResultSet đơn giản với một Adapter’s Result sẽ được trả về và sẵn sàng cho việc sử dụng. 8 Bài 4: Database và Model 5 ZendDbTable Gateway.  Sử dụng: – Ví dụ: use Zend\Db\TableGateway\TableGateway; $projectTable = new TableGateway('project', $adapter); $rowset = $projectTable->select(array('type' => 'PHP')); echo 'Projects of type PHP: '; $ $foreach ( rowset as projectRow) { echo $projectRow['name'] . PHP_EOL; } // or when expecting a single row: , $artistTable = new TableGateway('artist', $adapter); $rowset = $artistTable->select(array('id' => 2)); $artistRow = $rowset->current(); 9 var_dump($artistRow); Bài 4: Database và Model 5 ZendDbTable Gateway.  Sử dụng: – Phương thức select() có những lập luận tương tự như Zend\Db\Sql\Select::where() với việc bổ sung cũng được chấp nhận sẽ thông qua đối tượng Select , được sử dụng để xây dựng truy vấn SELECT. use Zend\Db\TableGateway\TableGateway; use Zend\Db\Sql\Select; $artistTable = new TableGateway('artist', $adapter); // search for at most 2 artists who's name starts with Brit, ascending $rowset = $artistTable->select(function (Select $select) { $select->where->like('name', 'Brit%'); 10 $select->order('name ASC')->limit(2); }); Bài 4: Database và Model 5 ZendDbTable Gateway.  Đặc điểm của Table Gateway – Features API cho phép mở rộng chức năng của đối tượng TableGateway cơ sở mà không cần phải mở rộng lớp cơ sở . – Với đối tượng TableGateway, đặc tính cần phải được đưa vào thông qua constructor. – Constructor có thể lấy Features trong ba dạng form khác nhau: single feature object, FeatureSet object, hoặc mảng các Feature object . 11 Bài 4: Database và Model 5 ZendDbTable Gateway. – Dưới đây là một số feature built-in và shipped với Zend\Db: • GlobalAdapterFeature: khả năng sử dụng global/static adapter mà không cần phải đưa nó vào ấmột TableGateway instance. Nó r t hữu dụng khi ta mở rộng việc sử dụng AbstractTableGateway: class MyTableGateway extends AbstractTableGateway { public function __construct() { $this->table = 'my_table'; $this->featureSet = new Feature\FeatureSet(); $this->featureSet->addFeature(new Feature\GlobalAdapterFeature()); $this->initialize(); } } // elsewhere in code in a bootstrap 12 , Zend\Db\TableGateway\Feature\GlobalAdapterFeature::setStaticAdapter($adapter); // in a controller, or model somewhere $table = new MyTableGateway(); // adapter is statially loaded Bài 4: Database và Model 5 ZendDbTable Gateway. – Dưới đây là một số feature built-in và shipped với Z d\Dben : • MasterSlaveFeature: khả năng sử dụng master adapter để insert(), update(), và delete() khi dùng slave adapter cho tất cả các select() operation (toán tử/ hoạt động). $table = new TableGateway('artist', $adapter, new Feature\MasterSlaveFeature($slaveAdapter)); 13 Bài 4: Database và Model 5 ZendDbTable Gateway. – Dưới đây là một số feature built-in và shipped với Z d\Dben : • MetadataFeature: khả năng populate TableGateway với thông tin của cột lấy từ đối tượng Metadata. Nó cũng sẽ lưu trữ thông tin khóa chính trong trường hợp RowGatewayFeature cần sử dụng thông tin này. $table = new TableGateway('artist', $adapter, new Feature\MeatadataFeature()); 14 Bài 4: Database và Model 5 ZendDbTable Gateway. – Dưới đây là một số feature built-in và shipped với Z d\Dben : • EventFeature: khả năng sử dụng đối tượng TableGateway với Zend\EventManager và để có thể đăng ký vào các sự kiện khác nhau trong một vòng đời của TableGateway. $table = new TableGateway('artist', $adapter, new Feature\EventFeature($eventManagerInstance)); 15 Bài 4: Database và Model 5 ZendDbTable Gateway. – Dưới đây là một số feature built-in và shipped với Z d\Dben : • RowGatewayFeature: khả năng cho select() trả về đối tượng ResultSet object lặp lại khi cần: $table = new TableGateway('artist', $adapter, new Feature\RowGatewayFeature('id')); $results = $table->select(array('id' => 2)); $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); 16 Bài 4: Database và Model 6 ZendDb RowGateway.  Zend\Db\RowGateway là một component con ẫcủa Zend\Db thực hiện m u Row Gateway từ PoEAA. ố ẫ Các đ i tượng Row Gateway có m u là một hàng trong CSDL và có những phương thức như save() và delete() giúp duy trì dòng này như một đối tượng trong CSDL.  Tương tự sau khi một dòng từ CSDL được lấy , ra, thao tác và save() trở lại CSDL ở đúng vị trí cũ, hoặc nó cũng có thể bị xóa từ bảng. 17 Bài 4: Database và Model 6 ZendDb RowGateway.  Interface cho một đối tượng Row Gateway đơn ầgiản chỉ c n thêm vào phương thức save() và delete và đây là một interface cần được giả định khi một component có một phụ thuộc dự kiến sẽ là một thể hiện của đối tượng RowGateway: interface RowGatewayInterface { public function save(); public function delete(); } 18 Bài 4: Database và Model 6 ZendDb RowGateway.  Sử dụng: – Hầu hết thời gian, RowGateway được sử dụng kết hợp với các đối tượng Zend\Db\ResultSet khác, cũng có thể sử dụng chúng độc lập . – Và để sử dụng chúng một cách độc lập đơn giản ta chỉ cần một Adapter và một bộ dữ liệu đi cùng. 19 Bài 4: Database và Model 6 ZendDb RowGateway.  Sử dụng: – Zend\Db\RowGateway\RowGateway trình bày ở dạng đơn giản của nó: Z d\Db\R G t \R G tuse en ow a eway ow a eway; // query the database $resultSet = $adapter->query('SELECT * FROM `user` WHERE `id` = ?', (2))array ; // get array of data $rowData = $resultSet->current()->getArrayCopy(); // row gateway $ G t R G t ('id' ' t bl ' $ d t )row a eway = new ow a eway , my_ a e , a ap er ; $rowGateway->populate($rowData); $rowGateway->first_name = 'New Name'; $ G t > () 20 row a eway- save ; // or delete this row: $rowGateway->delete(); Bài 4: Database và Model 6 ZendDb RowGateway. – Luồng công việc được mô tả phía trên rất đơn giản khi RowGateway được sử dụng kết hợp với TableGateway feature. Kết quả đạt được là một đối tượng Table Gateway khi dùng select() từ một bảng, ó ẽ t ột R ltS t à đó ó khả ăn s ạo ra m esu e m sau c n ng tạo ra một đối tượng Row Gateway hợp lệ: use Zend\Db\TableGateway\Feature\RowGatewayFeature; use Zend\Db\TableGateway\TableGateway; $table = new TableGateway('artist', $adapter, new RowGatewayFeature('id')); $results = $table->select(array('id' => 2)); 21 $artistRow = $results->current(); $artistRow->name = 'New Name'; $artistRow->save(); Bài 4: Database và Model 7 Database.  Sau khi đã thiết lập các phương thức cần thiết cho controller của module Product và tạo các view script chưa có nội dung, chúng ta cần phải xây dựng model cho ứng dụng .  Model là thành phần quan trọng của ứng dụng, nó liên quan tới CSDL Trong ZF2 chúng ta sử . , dụng lớp Zend\Db\TableGateway\TableGateway để tìm kiếm, thêm, cập nhật và xóa các dòng ra khỏi CSDL.  Sử dụng MySQL, thông qua PHP’s PDO driver, để tạo một CSDL cho ứng dụng. 22 Bài 4: Database và Model 7 Database.  Thực hiện – Ví dụ: tạo một CSDL có tên là “zend_app” có cấu trúc như sau: – Sau đó thêm vào một số dòng dữ liệu cần thiết: 23 Bài 4: Database và Model 8 Models.  Zend Framework không cung cấp sẵn Zend\Model component như model trong business logic, nó phụ thuộc vào quyết định của chúng ta muốn nó thực hiện công việc gì Có khá nhiều component . chúng ta có thể sử dụng khi cần.  Một cách tiếp cận là chúng ta có các lớp model tương ứng với các thực thể của ứng dụng, sau đó sử dụng các mapper objects để load và lưu các ểthực th vào CSDL.  Một cách tiếp cận khác là sử dụng một ORM như D t i h P loc r ne ay rope . 24 Bài 4: Database và Model 8 Models.  Trong bài này chúng ta tạo ra một model đơn ằgiản b ng cách tạo ra ProductTable class sử dụng Zend\Db\TableGateway\TableGateway class trong đó mội đối tượng Product là một, Product object (được biết như là một thực thể - entity).  Model này là một implementation của Table Data Gateway design pattern, nó cho phép tương tác với dữ liệu trong bảng 25 Bài 4: Database và Model 8 Models.  Thực hiện B ớ 1 Xâ d lớ th thể P d t t th– ư c : y ựng p ực ro uc rong ư mục Model: // module/Product/src/Product/Model/Product php: . namespace Product\Model; class Product { public $id; public $name; public $price; public $image public function exchangeArray($data) { $this->id = (isset($data['id'])) ? $data['id'] : null; $this->name = (isset($data['name'])) ? $data['name'] : null; $this->price = (isset($data['price'])) ? $data['price'] : null; $thi i (i t($d t ['i '])) ? $d t ['i '] ll 26 s-> mage = sse a a mage a a mage : nu ; } } Bài 4: Database và Model 8 Models.  Thực hiện Đối t th thể P d t là ột l PHP đ– ượng ực ro uc m c ass ơn giản. Để có thể làm việc với Zend\Db’s TableGateway class, chúng ta cần phải implement phương thức exchangeArray(). – Phương thức này sẽ chép dữ liệu từ mảng tới các thuộc tính của thực thể . 27 Bài 4: Database và Model 8 Models.  Thực hiện B ớ 2 Tiế th ầ hải t T bl Cl t th– ư c : p eo, c n p ạo a e ass rong ư mục Model của module – ProductTable. ProductTable sẽ có các phương thức cần thiết cho việc thực hiện các action khai báo trong controller phía trên: • Đặt một biến protected tên là $tableGateway được gán giá trị truyền vào từ controller trong phương thức khởi tạo của constructor. Chúng ta sẽ sử dụng nó để thực hiện các chức năng trong bảng dữ liệu tới Products • Chúng ta tạo ra các phương thức mà ứng dụng sẽ sử dụng để interface với table gateway . 28 Bài 4: Database và Model 8 Models. – Phương thức fetchAll() nhận tất cả các dòng của bảng Products từ CSDL và xem như là một ResultSet – Phương thức getProduct() nhận một dòng, là một đối tượng Product Ph thứ P d t() ừ t ột– ương c save ro uc v a ạo m dòng mới vào CSDL vừa cập nhật dòng đã tồn tại trong bảng của CSDL – Phương thức deleteProduct() xóa một dòng trong bảng . 29 Bài 4: Database và Model 8 Models.  Thực hiện namespace Product\Model; use Zend\Db\TableGateway\TableGateway; class ProductTable { protected $tableGateway; public function construct(TableGateway $tableGateway) __ { $this->tableGateway = $tableGateway; } public function fetchAll() { $resultSet = $this->tableGateway->select(); 30 return $resultSet; } Bài 4: Database và Model // continue public function getProduct($id) { $id (i t) $id = n ; $rowset = $this->tableGateway->select(array('id' => $id)); $row = $rowset->current(); if (!$row) { throw new \Exception("Could not find row $id"); } return $row; } // continue public function deleteProduct($id) { $this->tableGateway->delete(array('id' => $id)); } 31 } Bài 4: Database và Model // continue public function saveProduct(Product $product) { $data = array( 'name' => $product->name, 'price' => $product->price, ‘image' => $product->image, ); $id = (int)$product->id; if ($id == 0) { $this >tableGateway >insert($data);- - } else { if ($this->getProduct($id)) { $this->tableGateway->update($data array('id' => $id));, } else { throw new \Exception('Form id does not exist'); } 32 } } Bài 4: Database và Model 8 Models.  Thực hiện B ớ 3 Sử d S i M để ấ hì h t bl– ư c : ụng erv ce anager c u n a e gateway đưa vào ProductTable • Để thường xuyên sử dụng cùng một instance của ProductTable, chúng ta sẽ dùng ServiceManager để định nghĩa cách tạo ra nó. Việ à đ th hiệ t lớ M d l i• c n y ược ực n rong p o u e, nơ chúng ta tạo ra phương thức ServiceConfig(), nó được gọi tự động bằng ModuleManager và áp dụng cho ServiceManager. • Chúng ta có thể nhận nó trong controller khi chúng ta cần đến . 33 Bài 4: Database và Model 8 Models.  Thực hiện B ớ 3 Sử d S i M để ấ hì h t bl– ư c : ụng erv ce anager c u n a e gateway đưa vào ProductTable • Để cấu hình ServiceManager, chúng ta cung cấp tên của lớp (to be instantiated or a factory (closure or callback) that instantiates the object) khi ServiceManager. • Chúng ta thực hiện phương thức getServiceConfig() để cung cấp một factory mà tạo ra ProductTable. Thêm phương thức này vào cuối Module class. 34 Bài 4: Database và Model // module/Product/Module.php: namespace Product; use Product\Model\Product; use Product\Model\ProductTable; use Zend\Db\ResultSet\ResultSet; use Zend\Db\TableGateway\TableGateway; class Module { // getAutoloaderConfig() and getConfig() methods here // Add this method: bli f ti tS i C fi ()pu c unc on ge erv ce on g { return array('factories' => array( 'Product\Model\ProductTable' => function($sm) { $tableGateway = $sm->get('ProductTableGateway'); $table = new ProductTable($tableGateway); return $table; }, 'ProductTableGateway' => function ($sm) { $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Product()); return new TableGateway('product' $dbAdapter null 35 , , , $resultSetPrototype); },),);} } Bài 4: Database và Model 8 Models.  Thực hiện – Bước 3: • Phương thức này trả về một mảng các factory được kết hợp với nhau bởi ModuleManager trước khi chuyển tới ServiceManager. • Factory dành cho Product\Model\ProductTable sử dụng ServiceManager để tạo một ProductTableGateway để chuyển tới ProductTable. • Chúng ta cũng cho ServiceManager biết rằng ProductTableGateway được tạo ra bằng cách lấy một Zend\Db\Adapter\Adapter (cũng từ ServiceManager) và sử dụng nó để tạo ra một TableGateway object. • TableGateway sử dụng Product object khi nó tạo ra một dòng kết quả mới. TableGateway classes sử dụng prototype pattern cho việc tạo ra bộ kết quả và thực thể. 36 Bài 4: Database và Model 8 Models.  Thực hiện ố ầ ấ– Bước 4: Cu i cùng, c n phải c u hình ServiceManager • Để ServiceManager biết cách lấy Zend\Db\Adapter\Adapter bằng cách dùng một tên là Zend\Db\Adapter\AdapterServiceFactory mà chúng ta có thể cấu hình trong hệ thống cầu hình kết hợp. • ModuleManager của ZF2 tổng hợp các cấu hình từ mỗi file module.config.php của module sau đó đưa vào các file trong thư mục config/autoload (*.global.php và *.local.php). • Chúng ta sẽ thêm thông tin cấu hình CSDL vào file global.php. Ta cũng có thể dùng local.php (bên ngoài VCS

Các file đính kèm theo tài liệu này:

  • pdftailieu.pdf
Tài liệu liên quan