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à...
403 trang |
Chia sẻ: Khủng Long | Lượt xem: 2404 | Lượt tải: 1
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:
- tailieu.pdf