SlideShare a Scribd company logo
1 of 28
Xây dựng mô hình các thư mục như sau:

www/zfexam/application

www/zfexam/public/

www/zfexam/library
Tại thư mục library, bạn chỉ việc copy và thư viện zend, phiên bản mới nhất vào đây.

Thư mục pubic: bạn lần lượt tạo 2 file mới là: index.php và .htaccess

File index với nội dung như sau:
01 <?php
02 defined('APPLICATION_PATH')
03      || define('APPLICATION_PATH',
04                realpath(dirname(__FILE__) . '/../application'));
05 defined('APPLICATION_ENV')
06     || define('APPLICATION_ENV',
07                   (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
08                                              : 'production'));
09 set_include_path(implode(PATH_SEPARATOR, array(
10     dirname(dirname(__FILE__)) . '/library',
11      get_include_path(),
12 )));
13 require_once 'Zend/Application.php' ;
14 $application = new Zend_Application(
15      APPLICATION_ENV,
16      APPLICATION_PATH . '/configs/application.ini'
17 );
18 $application->bootstrap()->run();
Trong file .htaccess lại tiếp tục copy và past đoạn code sau:
1 RewriteEngine On
2 RewriteCond %{REQUEST_FILENAME} -s [OR]
3 RewriteCond %{REQUEST_FILENAME} -l [OR]
4 RewriteCond %{REQUEST_FILENAME} -d
5 RewriteRule ^.*$ - [NC,L]
6 RewriteRule ^.*$ index.php [NC,L]
Tại thư mục application bạn lại tạo các thư mục:

www/zfexam/application/controllers

www/zfexam/application/views

www/zfexam/application/models
www/zfexam/application/configs
Tại thư mục controllers tạo file:

www/zfexam/application/controllers/IndexController.php

Tại file IndexController.php copy nội dung sau:
1 <?php
2 class IndexController extends Zend_Controller_Action{
3      public function indexAction(){
4      }
5}
6 ?>
Tại thư mục views tạo thư mục:

www/zfexam/application/views/scripts/index/index.phtml

File index/index.phtml có nội dung như sau:
1 <h1>hello Zend Framework</h1>
Tại thư mục configs tạo file application.ini:

www/zfexam/application/configs/application.ini

Với nội dung:
[production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH
"/controllers"
Và tiếp tục tạo file bootstrap.php ở thư mục application

www/zfexam/application/bootstrap.php

Với nội dung:
1 <?php
2 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
3}
Và cuối cùng chúng ta cùng chạy:

http://localhost/zfexam/public/

Như vậy, bạn đã viết ứng dụng đầu tiên bằng Zend Framework rồi đấy.
Và cấu trúc Zend Framework như hình bên dưới:




Lưu ý : Để zend framework, bạn cần phải bật mod rewrite trên web server.

Cách bật mod rewrite:

Đầu tiên bạn cần tìm đến file httpd.conf (vì không biết các sử dụng web server nào nên tôi không
đưa ra đường dẫn cụ thể). Các bạn cũng có thể dùng chế độ tìm kiếm file trong window để tìm
file này.

Sau đó tìm đến dòng

LoadModule rewrite_module modules/mod_rewrite.so

Và bỏ đi dấu thăng của nó nếu máy của bạn vẫn chưa bật mod rewrite.

Cuối cùng bạn cẩn restart lại apache để hệ thống cập nhật thông tin mà bạn vừa chỉnh sửa từ hệ
thống.




Ví dụ xét liên kết:
http://qhonline.info/book/viewbook/

Như vậy book được xem là một controller và viewbook được xem là một action của controller
đó. Khi hoạt động, trong controller bạn sẽ khởi tạo những action như mong muốn thông qua việc
thiết lập phương thức một cách cụ thể.

Ví dụ:
1 <?php
2 class IndexController extends Zend_Controller_Action{
3        public function indexAction(){
4        }
5}
Như vậy IndexController cho ta Controller mang tên index và indexAction cho ta action là index.

Khi đó bạn bắt buộc phải khởi tạo trong views một thư mục ứng với controller là index trong
scripts. Và file index.phml ứng với action là index.

Xét ví dụ khác:
1 <?php
2 class BookController extends Zend_Controller_Action{
3 public function indexAction(){
4 }
5 public function viewbookAction(){
6 }
7}
Ở ví dụ này cho ta biết Controller là Book, 2 action là index và viewbook.

Như vậy, để chạy được ứng dụng. Bạn cần tạo thư mục Book trong views ứng với controller và
file index.phtml, viewbook.phtml.

Cụ thể:

application/controller/BookController.php

application/views/scripts/Book/index.phtml

application/views/scripts/Book/viewbook.phtml

B- Tìm hiểu nội dung file index.php và application.ini trong Zend Framework:

Nội dung đầy đủ file index.php
01 <?php
02 defined('APPLICATION_PATH')
03        || define('APPLICATION_PATH',
04                  realpath(dirname(__FILE__) . '/../application'));
05 defined('APPLICATION_ENV')
06     || define('APPLICATION_ENV',
07                  (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
08                                             : 'production'));
09 set_include_path(implode(PATH_SEPARATOR, array(
10     dirname(dirname(__FILE__)) . '/library',
11      get_include_path(),
12 )));
13 require_once 'Zend/Application.php' ;
14 $application = new Zend_Application(
15      APPLICATION_ENV,
16      APPLICATION_PATH . '/configs/application.ini'
17 );
18 $application->bootstrap()->run();
Tiếp theo chúng ta sẽ tìm hiểu xem bên trong file index.php này có những điểm gì cần lưu ý.
1 defined('APPLICATION_PATH')
2     || define('APPLICATION_PATH',
3                  realpath(dirname(__FILE__) . '/../application'));
Dòng này khai báo cho Zend Framework biết bạn đang đặt thư mục application ở đâu thông
qua một hằng APPLICATION_PATH. Đây là hằng mà bạn sẽ dùng rất nhiều trong các khai báo
cấu hình sau này.
1 defined('APPLICATION_ENV')
2     || define('APPLICATION_ENV',
3                  (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
4                                             : 'production'));
Dòng này cho phép đọc thông tin phân đoạn có tên production ở file application.ini ở bên dưới.
Và ta đưa chữ production vào một hằng là APPLICATION_ENV.
1 set_include_path(implode(PATH_SEPARATOR, array(
2     dirname(dirname(__FILE__)) . '/library',
3      get_include_path(),
4 )));
Dòng này làm nhiệm vụ load nội dung của thư viện library nơi mà bạn chứa thư viện của zend.
Nôm na có thể hiểu là, nếu bạn sử dụng dòng này. Thì ở phần dưới và những trang khác, thay vì
bạn phải gõ: require_once 'Library/Zend/Application.php' Thì giờ bạn chỉ cần gõ: require_once
'Zend/Application.php' . Vì mặc định thư viện đã được nạp vào rồi.
1 require_once 'Zend/Application.php' ;
2 $application = new Zend_Application(
3      APPLICATION_ENV,
4      APPLICATION_PATH . '/configs/application.ini'
5 );
Tiếp tới, chúng ta nạp nội dung trang Application.php và tiếp tục gọi trang application.ini ở thư
mục config. Và nếu bạn chú ý, sẽ thấy chúng ta sử dụng 2 hằng vừa khởi tạo là
APPLICATION_ENV và APPLICATION_PATH để lấy thông tin.
1 $application->bootstrap()->run();
Và cuối cùng là việc thực thi lệnh bằng hàm run().

Khi chúng ta đã hiểu được vấn đề, thì chúng ta có thể viết chúng gọn lại theo cách mà ta hiểu.
01 <?php
02 define('APPLICATION_PATH',
03               realpath(dirname(__FILE__) . '/../application'));
04 define('APPLICATION_ENV','production');
05 set_include_path(dirname(dirname(__FILE__)) . '/library');
06 require_once 'Zend/Application.php' ;
07 $application = new Zend_Application(
08     APPLICATION_ENV,
09      APPLICATION_PATH . '/configs/application.ini'
10 );
11 $application->bootstrap()->run();
Tiếp tới ta tìm hiểu file application.ini để xem nó thể hiện thông tin gì:
1 [production]
2 phpSettings.display_startup_errors = 0
3 phpSettings.display_errors = 0
4 bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
5 bootstrap.class = "Bootstrap"
  resources.frontController.controllerDirectory = APPLICATION_PATH
6
  "/controllers"
Dòng đầu tiên có chức năng khởi tạo phân đoạn mang giá trị [production]. Bởi vì trong file này
chúng ta chia làm nhiều phân đoạn một cách rõ ràng. Ví dụ phân đoạn chứa cơ sở dữ liệu, phân
đoạn chứa thông tin layout, kết nối CSDL,….
1 [production]
2 phpSettings.display_startup_errors = 0
3 phpSettings.display_errors = 0
Hai dòng này cho phép bạn có bật tính năng báo lỗi của ZEND FRAMEWORK hay không, nếu
có bạn sẽ sửa giá trị thành 1.
1 bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
2 bootstrap.class = "Bootstrap"
Hai dòng này cho phép bạn tìm tới file bootstrap.php để thông qua nó tương tác các thư viện hàm
trong ZEND FRAMEWORK. Đồng thời chỉ định tên gọi của class là Bootstrap. Ở đây bạn
cũng cần lưu ý là tên class trong file Bootstrap.php phải cùng tên với Bootstrap mà bạn đã khai
báo ở application.ini.
    resources.frontController.controllerDirectory = APPLICATION_PATH
1
    "/controllers"
Dòng này chỉ ra đường dẫn tới thư mục controllers trong thư mục application của chúng ta.
Trước tiên, ta xét lại cấu trúc mặc định của hệ thống qua tấm hình bên dưới:




Như chúng ta thấy, với cấu hình ở trên thì trong application có 3 thư mục chủ đạo là controllers,
models, views. Vậy để tạo ứng dụng theo mô hình module ta tạo 1 thư mực modules. Trong thư
mục này ta tạo tiếp 2 module là default và admin theo cấu trúc:

zf2/application/modules/default

zf2/application/modules/admin

Tại mỗi module default và admin ta lại tạo tiếp 3 thư mục con là controllers, models, views.
Theo cấu trúc.

Module default:

zf2/application/modules/default/controllers

zf2/application/modules/default/models

zf2/application/modules/default/views

Module admin:

zf2/application/modules/admin/controllers

zf2/application/modules/admin/models

zf2/application/modules/admin/views
Tại các thư mục controllers này lần lượt tạo các file tên IndexController.php với nội dung như
sau:

File IndexController.php của module default
1 <?php
2 class IndexController extends Zend_Controller_Action{
3       public function indexAction(){
4       }
5
6}
File IndexController.php của module admin
1 <?php
2 class Admin_IndexController extends Zend_Controller_Action{
3       public function indexAction(){
4       }
5
6}
Nếu để ý kỹ, chúng ta có thể thấy rằng trước tên mỗi class ta lại thêm tên module của chúng ở
trước. Đây là kỹ thuật lazy loading trong OOP, được sử dụng để triệu nạp file controller trong
từng module của zend framework. Riêng đối với module default là module mặc định nên trong
class controller ta không cần khai báo thêm tên module giống với module admin.

Tiếp tục, ta di chuyển 2 file index.php và .htaccess ra khỏi thư mục public theo cấu trúc như sau:

www/zf2/index.php

www/zf2/.htaccess

Vì chúng ta đã di chuyển file index.php ra khỏi thư mục public và nó ngang cấp với thư mục
application nên lúc này đường dẫn triệu nạp trong file cũng sẽ thay đổi. File index.php cũ của
chúng ta:
01 <?php
02 define('APPLICATION_PATH',
03               realpath(dirname(__FILE__) . '/../application'));
04 define('APPLICATION_ENV','production');
05 set_include_path(dirname(dirname(__FILE__)) . '/library');
06 require_once 'Zend/Application.php' ;
07 $application = new Zend_Application(
08     APPLICATION_ENV,
09       APPLICATION_PATH . '/configs/application.ini'
10 );
11 $application->bootstrap()->run();
Vì giờ file index.php đã đưa ra ngoài public. Nên chắc chắn đường dẫn vào thư mục application
sẽ thay đổi. Khi đó sẽ là: realpath(dirname(__FILE__) . '/application');

Vậy hằng APPLICATION_PATH cũng chúng ta đã thay đổi và trỏ đường dẫn tới thư mục
application.

Tiếp tục ta cấu hình cho ứng dụng tìm tới được thư mục library.

set_include_path(APPLICATION_PATH . '/../library');

Bạn hiểu thế nào về đoạn cấu hình này ?. Vì hằng APPLICATION_PATH ở trên đã có thể tìm
thấy được thư mục application. Cho nên từ thư mục ấy ta back trở ra để tìm tới thư mục library.
Vì thế trước library ta có dùng "/../library" là vì vậy.

Vậy file index.php củng chúng ta sau khi chỉnh sửa sẽ như sau:
01 <?php
02 define('APPLICATION_PATH',
03               realpath(dirname(__FILE__) . '/application'));
04 define('APPLICATION_ENV','production');
05 set_include_path(APPLICATION_PATH . '/../library');
06 require_once 'Zend/Application.php' ;
07 $application = new Zend_Application(
08     APPLICATION_ENV,
09      APPLICATION_PATH . '/configs/application.ini'
10 );
11 $application->bootstrap()->run();
Tiếp tục ta tạo file index.phtml trong từng thư mục views của từng module.

www/zf2/application/modules/default/views/scripts/index/index.phtml
1 <h1>Hello Zend Framework – Default Module<h1>

www/zf2/application/modules/admin/views/scripts/index/index.phtml

1 <h1>Hello Zend Framework – Admin Module<h1>
Chạy thử ứng dụng xem nào:

http://localhost/zf2/default
http://localhost/zf2/admin/index
Bị lỗi rồi phải không nào ?. Ứng dụng bị lỗi là vì chúng ta vẫn chưa cấu hình để tìm thấy được
thư mục module.

Vì thế, để giải quyết. Tả mở file application.ini trong thư mục configs ra và thêm vào 2 dòng sau:
1 resources.frontController.moduleDirectory=APPLICATION_PATH "/modules"
2 resources.modules=""

Dòng ở trên làm gì vậy ?. Câu trả lời nó chỉ ra đường dẫn tới thư mục modules của chúng ta. Và
dòng thứ 2 chỉ ra ta đang gọi cơ chế module autoload. Khi đó các class, model, form,… sẽ được
tự động nạp vào từng module của chúng ta.

Chạy xem lại xem nào.

Kết quả sẽ như thế này đây



Hình ảnh cấu trúc multi Module trong Zend Framework (file .htaccess không hiển thị trong mô
hình cây này).
A- Tìm hiểu quy tắc hoạt động của Zend View

Trong controller của zend framework khi chúng ta khởi tạo một action (hành động). Thì tương
đương tại thư mục views/scripts/tên_controller/hành_động.phtml.

Ví dụ:

Nếu là NewsController và addAction() thì chúng ta sẽ tạo view theo cấu trúc:

Views/scripts/news/add.phtml

Như vậy, Zend Framework sẽ tự động gọi views của action add khi người dùng tham chiếu tới
action add qua đường dẫn. Vậy những gì mà chúng ta trình bày ở view add.phtml sẽ hiển thị cho
người dùng thấy khi họ tham chiếu tới action add.

Vậy để truyền tham số mà chúng ta thao tác ở controller cho view như thế nào ?.

Zend Framework cho phép người sử dụng truyền tham số thông qua phương thức:

$this->view->tên_biến;

Và tại các file view có đuôi .phtml chúng ta chỉ cần sử dụng cú pháp: $this->tên_biến để lấy giá
trị mà chúng ta đang truyền từ controller.

Ví dụ ta tạo controller tên: IndexController.php với nội dung:
1 <?php
2 class IndexController extends Zend_Controller_Action {
3        public function indexAction(){
4            $this->view->string= "hello Zend Framework – QHOnline.Info";
5        }
6
7}
Tại thư mục views/scripts/index ta tạo file tên index.phtml với nội dung:
1 <?php
2 echo "<h1>".$this->string."</h1>";
3 ?>


Và kết quả sẽ ra là: Hello Zend Framework – QHOnline.Info

Như bạn thấy ta có thể truyền tham số và nhận tham số dễ dàng tại view với quy tắc ở trên phải
không nào.

Trường hợp truyền một mảng thì có cách truyền như sau:
01 <?php
02 class IndexController extends Zend_Controller_Action{
03    public function indexAction() {
04 $data= array(
05     'title' => 'Zend Framework',
06     'author'=> 'Kenny',
07     'date' => '20-11-2009',
08     'website'=> 'www.QHOnline.Info'
09 );
10 $this->view->info =$data;
11       }
12 }
Tại file view ta viết lại như sau:
1 <?php
2 foreach($this->info as $k => $v)
3{
4 echo "<b>$k</b>: $v<br />";
5}
6 ?>
Chạy thử nghiệm: http://localhost/zfexample/index/index

Kết quả: dữ liệu của mảng sẽ được hiển thị như mong đợi.

Trong trường hợp, chúng ta không muốn action phải gọi view thì tại action trong controller mà ta
muốn, thêm vào phương thức sau:

$this->getHelper('viewRenderer')->setNoRender();

Khi sử dụng phương thức này thì tại action đó ta không cần phải tạo file trong thư mục views. Vì
nó bỏ qua việc render file view của action.

B- Nạp 1 file khác trong view như thế nào ?

Để thực hiện việc nạp 1 file khác vào view trong zend framework. Chúng ta có thể gọi trong
view thông qua phương thức:

echo $this->render("Tên_file.phtml");

Lưu ý là file của chúng ta phải lưu trong thư mục views/scripts/. Vì mặc định trong zend view
các file xử lý sẽ nằm tại thư mục views/scripts/

Ví dụ: Tạo action demo trong IndexController với nội dung như sau:
1 <?php
2 class IndexController extends Zend_Controller_Action{
3 function demoAction(){
4  $this->view->hello="Hello Zend Framework - QHOnline.Info";
5 }
6}
Tạo tiếp file demo.phtml trong thư mục views/scripts/index/
1 <?php
2 echo "<h1>".$this->hello."</h1>";
3 echo $this->render("qhonline.phtml");
4 ?>
Tạo tiếp file qhonline.phtml trong thư mục: views/scripts
1 <h2>Khoa hoc PHP Online Version 2.0</h2>
Chạy thử nghiệm: http://localhost/zfexample/index/demo

Kết quả: dữ liệu trả về với nội dung như mong đợi.

C- Thiết lập thông tin cơ bản trong zend view:

Zend view hỗ trợ người dùng những thư viện cấu hình cơ bản trong HTML như <title>, <link>,
<script>,… Như vậy để sử dụng được chúng ta cần thiết lập chúng thông qua các controller và từ
nó đổ tham số ra view.

a) Thiết lập chuẩn XHTML:

Cú pháp: doctype("Tham số")

Tham số chính là những chuẩn mà chúng ta mong muốn.

b) Thiết lập CSS:

Cú pháp: appendStylesheet(URL,Định dạng, Điều kiện)

Tương đương:

<link href="URL" media="??" />

c) Thiết lập thẻ Title:

Cú pháp: headtitle("Tieu de")

Tương đương:

<title> Tieu de </title>

d) Thiết lập thẻ Meta:

Cú pháp: appendName("keyword","Zend Framework,");

Trường hợp thêm description ta có:
offsetSetName("1","description","Khoa hoc PHP Framework tai QHOnline")

Tham số đầu là vị trí, tham số sau là tên description và tham số thứ 3 là thông tin.

e) Thiết lập thẻ script:

Cú pháp: appendFile(URL,"text/javascript")

Trường hợp nạp file js thứ 2

offsetSetFile("1","URL","text/javascript")

Ví dụ: Tạo testAction() trong controller index với nội dung:
01 function testAction(){
02 $baseurl=$this->_request->getbaseurl();
03 $this->view->doctype();
04 $this->view->headtitle("QHOnline.Info - Chapter 3: Zend Framework");
    $this->view->headMeta()->appendName("keyword","Zend
05
   Framework,Codeigniter,PHP Framework");
    $this->view->headMeta()->offsetSetName("1","description","Khoa hoc PHP
06
   Framework tai QHOnline");
    $this->view->headLink()-
07
   >appendStylesheet($baseurl."/public/css/test.css");
    $this->view->headscript()-
08
   >appendFile($baseurl."/public/js/test.js","text/javascript");
     $this->view->headscript()-
09
   >offsetSetFile("1",$baseurl."/public/js/test2.js","text/javascrip
10 }
Tạo tiếp file test.phtml tại thư mục: views/scripts/index với nội dung:
01 <?php echo $this->doctype() ?>
02 <html>
03 <head>
04     <?php echo $this->headTitle() ?>
05      <?php echo $this->headMeta() ?>
06      <?php echo $this->headLink() ?>
07     <?php echo $this->headScript() ?>
08 </head>
09 <body onload="test()">
10 <div class="test">Hello Zend Framework – QHOnline.Info</div>
11 </body>
12 </html>
Chạy thử nghiệm: http://localhost/zfexample/index/test

Kết quả: Title, meta, Css và javascript sẽ có tác dụng
Như bạn thấy đấy, ở trong đoạn code trên testAction() ta sử dụng phương thức:

$baseurl=$this->_request->getbaseurl();

Đó là bởi vì, những gì mà chúng ta muốn tương tác được trong view như css, javascript, hình ảnh
hiển thị thì buộc chúng ta phải lấy được đường dẫn hiển thị ứng dụng zend framework.

Và với $baseurl ở trên thực chất là chúng ta sẽ lấy được thư mục hiện hành của ứng dụng là
/zfexample. Và từ đó ta gọi tiếp các thông tin còn lại như css, js và hình ảnh hiển thị.




-------------------------o0o-----------------------------



Khi sử dụng layout, thì mọi dữ liệu của view đểu sẽ hiển thị trong vùng chỉ định của layout đó
mà chúng ta không cần phải khai báo chúng trong từng view một. Như vậy, nói cách khác chúng
ta sẽ không cần quan tâm đến bộ cục của layout khi làm việc với view. Mà chỉ quan tâm đến dữ
liệu, vai trò mà view đó thể hiện như thế nào mà thôi.

Để làm được điều đó, trong file application.ini ta thêm vào 2 dòng sau:
1 resources.layout.layout="layout"
2 resources.layout.layoutPath=APPLICATION_PATH "/layouts/scripts"
Ý nghĩa của 2 dòng này như thế nào ?.
+ Dòng đầu tiên cho ta biết file chứa layout của chúng ta tên là layout
+ Dòng thứ hai cho ta biết đường dẫn tới file layout này như thế nào.

Với 2 dòng ở trên ta hoàn toàn có thể cấu hình thay đổi tên và đường dẫn theo ý thích của riêng
ta một cách dễ dàng.
Kế tới, ta tạo thư mục layouts/scripts. Và tạo file layout.phtml trong thư mục này với nội dung
như sau:
01 <?php echo $this->doctype() ?>
02 <html>
03 <head>
04     <?php echo $this->headTitle() ?>
05         <?php echo $this->headMeta() ?>
06         <?php echo $this->headLink() ?>
07     <?php echo $this->headScript() ?>
08 </head>
09 <body>
10     <?php
11                echo $this->layout()->content;
12         ?>
13 </body>
14 </html>
Bạn thấy đấy, cấu trúc của nó giống với phần view ở bài tìm hiểu cơ bản về zend view phải
không nào. Chỉ có sự khác biệt là phần nội dung body. Chúng ta dùng cú pháp:
1 $this->layout()->content;
Cú pháp này sẽ gọi các view của controller vào để hiện thị trên bố cục này.

Vậy trong IndexController.php ta viết đoạn lệnh như sau:
1 <?php
2 class IndexController extends Zend_Controller_Action{
3      public function init(){
4          $this->view->headTitle("QHOnline - Zend Layout")
5      }
6      public function indexAction(){
7                echo "<h1>Welcome to Zend Framework - QHOnline.Info";
8      }
9}
Ở đoạn code phía trên, tôi sử dụng phương thức init(). Đây là phương thức mặc định sẽ được gọi
đầu tiên khi chúng ta tiến hành chạy controller này. Và dĩ nhiên, khi bạn chạy bất kể một action
nào thì init() cũng sẽ được gọi trước hết. Và trong ví dụ này, công việc của init() là hiển thị thông
tin tiêu đề của trình duyệt là QHOnline- Zend Layout.

Khi bạn chạy ứng dụng, sẽ thấy view của chúng ta được nằm trong một bố cục mà bạn đã bố trí
một cách hợp lý.

Ngoài cách cấu hình trực tiếp trong file application.ini ra, chúng ta cũng có thể cấu hình và gọi
trực tiếp chúng bởi việc gọi nạp trong các controller như sau:
01 <?php
02 class IndexController extends Zend_Controller_Action{
03         public function init(){
04           $option=array(
05                "layout" => "layout",
06                "layoutPath" => APPLICATION_PATH."/layouts/scripts/"
07              );
08              Zend_Layout::startMvc($option);
09                $this->view->headTitle("QHOnline - Zend Layout")
10         }
11         public function indexAction(){
12             echo "<h1>Welcome to Zend Framework - QHOnline.Info";
13         }
14 }
Như bạn thấy đấy, ở trên tôi tạo ra một mảng chứa 2 tham số là layout để chứa tên file và đường
dẫn của layout nhằm gọi tới thư mục chứa layout. Sau đó tôi gọi lớp Zend_Layout đồng thời gọi
phương thức starMVC() để truyền tham số mà chúng ta vừa thiết lập trong mảng.

Khi chạy ứng dụng thì kết quả hiển thị so với phương pháp cấu hình trong application là như
nhau.

Vậy sự khác biệt giữa hai phương pháp cấu hình này là gì ?.

+ Phương pháp cấu hình bằng application.ini cho phép ta chỉ thiết lập một lần, sau đó các
controller không cần phải thiết lập lại. Nhưng chúng chỉ cố định duy nhất một layout cho tất cả
ứng dụng.

+ Phương pháp cấu hình trực tiếp tuy phải cấu hình trong từng controller nhưng có thể cho ta tùy
chọn thay đổi theo chiều hướng multi layout cho từng module hoặc controller mà ta muốn một
cách dễ dàng.

Sử dụng 2 phương pháp này thế nào và ra sao là còn tùy vào sự linh động và sáng tạo trong lập
trình của các bạn. Kết thúc bài này, tôi đã hướng dẫn bạn sử dụng layout trong zend framework
để tạo master page đồng thời hướng tới khái niệm multi layout cho ứng dụng với những tùy chọn
mà bạn mong muốn. Trong bài tới, chúng ta sẽ cùng tìm hiểu về tương tác cơ sở dữ liệu trong
zend framework ra sao, qua đó vận dụng model trong zend framework như thế nào.




Vậy trước hết, ta tìm hiểu xem model là gì ?. Và tại sao phải sử dụng model ?. Model là tầng xử
lý những tác vụ liên quan đến tương tác cơ sở dữ liệu từ những yêu cầu của controller. Model
xử lý và trả về kết quả dưới dạng một mảng dữ liệu, khi đó thông qua view ta sẽ đẩy nội dung
của mảng dữ liệu ấy ra bên ngoài. Việc tách biệt tầng model có rất nhiều thuận lợi, trước là dễ
quản lý sau là dễ nâng cấp và phát triển trong tương lai của mã nguồn.

Để tương tác được với Model thì trước tiên ta phải kết nối được với cơ sở dữ liệu. Vậy ta tạo 1
bảng user với các cú pháp như sau:
01 CREATE TABLE user (
02   id int(10) unsigned NOT NULL AUTO_INCREMENT,
03     username varchar(50) NOT NULL,
04     password char(32) NOT NULL,
05     level int(1) NOT NULL DEFAULT '1',
06     PRIMARY KEY (id)
07 );
08 INSERT INTO 'user' (username,password,level) VALUES('admin', '12345', 2);
09 INSERT INTO 'user' (username,password,level) VALUES('kenny', '12345', 2);
10 INSERT INTO 'user' (username,password,level) VALUES('jacky', '12345', 1);
11 INSERT INTO 'user' (username,password,level) VALUES('Lena', '12345', 1);
Tiếp tục ta kết nối với cơ sở dữ liệu bằng cách thêm vào file application.ini của chúng ta những
đoạn lệnh sau:
1 resources.db.adapter = "Pdo_mysql"
2 resources.db.params.host = "localhost"
3 resources.db.params.username = "root"
4 resources.db.params.password = ""
5 resources.db.params.dbname = "qhonline"
Đoạn thông tin này khai báo cho hệ thống biết các tham số như host, user, pass, dbname.

Sau khi đã kết nối được với cơ sở dữ liệu, tiếp theo. Chúng ta sẽ tạo file User.php trong thư mục
Model với nội dung như sau:
1 <?php
2 class Model_User extends Zend_Db_Table_Abstract{
3     protected $_name="user";
4     protected $_primary="id";
5     public function listall(){
6         return $this->fetchall()->toArray();
7     }
8}
Qua đoạn lệnh trên ta hiểu phần nào về quy tắc định nghĩa một lớp model trong zend
framework. Vì tất cả các file nằm trong thư mục Model nên áp dụng theo cơ chế lazy loading ta
có quy tắc định nghĩa: Model_Tênfile. Cụ thể ở đây tôi tạo ra file User.php, nên lớp của tôi định
nghĩa sẽ là Model_User.

Lưu ý là thư mục Models của chúng ta có s, nhưng khi định nghĩa thì chúng ta bỏ qua s và viết
bình thường là Model.

Trong lớp Model_User ở trên, ta kế thừa lớp Zend_Db_Table_Abstract. Và khai báo tên bảng,
tên khóa chính thông qua hai thuộc tính $_name và $_primary. Cuối cùng, ta định nghĩa phương
thức listall() và dùng phương thức fetchall() để lấy toàn bộ dữ liệu vốn có trong bảng user.

Ở đây zend framework sử dụng cơ chế Active Record. Nên phương thức $this->fetchall() nó
tương đương với cú pháp lặp toàn bộ dữ liệu từ câu truy vấn select * from user vậy.

Sau cùng, ta tạo lớp UserController trong file controllers/UserController.php với nội dung sau:
1 <?php
2 class UserController extends Zend_Controller_Action{
3     public function indexAction(){
4         $muser=new Model_User;
5          echo "<pre>";
6          print_r($muser->listall());
7          echo "</pre>";
8      }
9}
Lưu ý là ta phải tạo trong thư mục views/scripts/user/index.phtml để controller tìm kiếm thấy
view khi được gọi. (xem bài tìm hiểu về view trong zend framework).

Để sử dụng được Model trong controller ta phải khởi tạo đối tượng từ lớp Model mà ta đã định
nghĩa ở trên. Sau đó từ đối tượng ta lại gọi các phương thức muốn thực thi. Lệnh <pre> ở trên
được dùng để trình bày dữ liệu dạng mảng.

Chạy thử nghiệm với đường dẫn: http://localhost/zfexam/user/

Kết quả sẽ thông báo lỗi:

Fatal error: Class 'Model_User' not found in
C:xampphtdocszfexamapplicationcontrollersUserController.php on line 4

Hệ thống của chúng ta chưa hiểu được lớp Model_User. Vì thế ta cần phải định nghĩa như sau
trong file bootstrap.php:
01 <?php
02 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
03         protected function _initAutoload(){
04             $autoloader = new Zend_Application_Module_Autoloader(array(
05                            'namespace' => '',
06                            'basePath' => dirname(__FILE__),
07                      ));
08             return $autoloader;
09         }
10 }
Như các bạn thấy đấy, ta đã thêm vào phương thức autoload để định nghĩa cho hệ thống biết
được đường dẫn tới các lớp mà ta tạo trong Model và form sau này.

Chạy thử nghiệm lại với đường dẫn: http://localhost/zfexam/user/
Kết quả sẽ hiển thị danh sách user dưới dạng mảng như ta mong đợi.

Một số phương thức thường dùng trong lớp Zend_Db_Table

1- Thao tác liệt kê và nhận dữ liệu:

Để có thể thực hiện các thao tác liệt kê dữ liệu đầy đủ và chi tiết. Chúng ta cần sử dụng phương
thức:
1 $this->select();
Và từ phương thức này, chúng ta sẽ gọi các thao tác khác liên quan như điều kiện, giới hạn, sắp
xếp,…
1 $query=$this->select();
+ Liệt kê dữ liệu theo cột:
1 $query->from('tên_bảng',array('cột 1','cột 2'));
+ Liệt kê dữ liệu với một điều kiện:
1 $query->where('cột =?','giá trị');
Cú pháp ở trên cho ta liệt kê dữ liệu với điều kiện cột bằng giá trị nào đó. Quy tắc trong zend
framework đối với mệnh đề where là tên cột, rồi đến phép so sánh, rồi đến ký hiệu "?". Và sau
cùng là mới là giá trị.

+ Sắp xếp dữ liệu theo cột thuộc tính
1 $query->order('tên_cột ASC hoặc DESC');
+Giới hạn dữ liệu hiển thị
1 $query->limit(vị trí bắt đầu, số record muốn hiển thị);
+ Hiển thị tất cả thông tin:
1 $this->fetchall();
Trường hợp hiển thị với các điều kiện ở phía trên thì ta truyền $query vào fetchall()
1 $this->fetchall($query);
+ Hiển thị 1 dòng dữ liệu
1 $this->fetchRow();
Ví dụ đầy đủ về hiển thị dữ liệu:
1 public function listuser(){
2     $data=$this->select();
3        $data->from('user',array('username','id'));
4        $data->where('id > ?',1);
5        $data->order('username DESC');
6        $data->limit(3);
7        $data=$this->fetchAll($data);
8        return $data;
9}
2- Thao tác thêm, xóa, sửa dữ liệu:

+ Thêm dữ liệu:
1 $this->insert($data);
Ví dụ:
1 public function insert_user($data){
2
3        $this->insert($data);
4}
+ Sửa dữ liệu:
1 $this->update($data,$where);
Ví dụ:
1 public function update_user($data,$where){
2       $where="id='1'";
3        $this->update($data,$where);
4}
Với $data của chúng ta là một mảng dữ liệu:
1 $data=array(
2              "username" => "kenny",
3                  "password" => "12345",
4                  "level" => "2"
5 );
+ Xóa dữ liệu:
1 $this->delete($where);
Ví dụ:
1 public function delinfo($id){
2     $where="id=".$id;
3        $this->delete($where);
4}
Kết thúc bài này, ta đã hiểu được cơ bản về cách thức sử dụng Model trong Zend Framework,
đồng thời cũng nắm được phần nào về các phương thức phổ biến thường sử dụng trong ứng
dụng. Trong bài kế tiếp, tôi sẽ hướng dẫn các bạn tìm hiểu về phương pháp tương tác với cơ sở
dữ liệu trên lớp Zend_Db. Qua đó có sự tùy biến tốt hơn trong việc viết ứng dụng trên zend
framework




Trước hết, ta cần tìm hiểu về lớp Zend_Registry. Đây là thư viện tạo ra một giá trị toàn cục
trong ứng dụng của chúng ta, nó có thể chứa giá trị, mảng và một đối tượng. Để thiết lập ta sử
dụng cú pháp:
1 Zend_Registry::set('tên','giá trị');
Sau khi tiết thiết lập, ta có thể lấy giá trị ở bất kỳ đâu bởi cú pháp:
1 Zend_Registry::get('tên');
Trong bài này, ta sử dụng chúng để lưu trữ hành động kết nối với cơ sở dữ liệu của chúng ta.

Tạo cơ sở dữ liệu và thêm dữ liệu vào bảng theo cú pháp sau:
01 CREATE TABLE user (
02   id int(10) unsigned NOT NULL AUTO_INCREMENT,
03     username varchar(50) NOT NULL,
04     password char(32) NOT NULL,
05     level int(1) NOT NULL DEFAULT '1',
06     PRIMARY KEY (id)
07 );
08 INSERT INTO 'user' (username,password,level) VALUES('admin', '12345', 2);
09 INSERT INTO 'user' (username,password,level) VALUES('kenny', '12345', 2);
10 INSERT INTO 'user' (username,password,level) VALUES('jacky', '12345', 1);
11 INSERT INTO 'user' (username,password,level) VALUES('Lena', '12345', 1);
Khai báo kết nối cơ sở dữ liệu tại file application/configs/application.ini như sau:
1 resources.db.adapter = "Pdo_mysql"
2 resources.db.params.host = "localhost"
3 resources.db.params.username = "root"
4 resources.db.params.password = ""
5 resources.db.params.dbname = "qhonline"
Tiếp tục, mở file bootstrap.php thêm đoạn code sau:
1 <?php
2 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
3      protected function _initDatabase(){
4          $db = $this->getPluginResource('db')->getDbAdapter();
5              Zend_Registry::set('db', $db);
6      }
7}
Theo đoạn code trên, ta thêm vào phương thức initDatabase(). Đây là phương thức sẽ được triệu
gọi khi chạy ứng dụng. Tại đây, ta lấy thông tin kết nối từ nội dung đã cấu hình ở file
application.ini.

Kế tới, ta thực hiện việc tạo registry để lưu trữ đối tượng kết nối này.
Tại thư mục Models, ta tạo file tên User.php
Với nội dung lớp này như sau:
01 <?php
02 class Model_User{
03         protected $db;
04         public function __construct(){
05              $this->db=Zend_Registry::get('db');
06         }
07         public function listall(){
08             $sql=$this->db->query("select * from user order by id DESC");
09              return $sql->fetchAll();
10         }
11 }
Như bạn thấy, tại lớp Model_User này trước hết ta tạo một construct() lấy giá trị từ registry để
đưa vào thuộc tính tên $db. Để mỗi khi ta khởi tạo đối tượng thì đối tượng kết nối đã được tạo
sẵn.

Kế đến ta tạo phương thức listall() thực hiện công việc liệt kê toàn bộ người dùng có trong bảng
user. Lúc này, để thực hiện được câu truy vấn thì ta dùng phương thức query() chạy. Và lấy kết
quả bới phương thức fetchAll() .

Tiếp tục, tại controller User ta gọi model như sau:
01 <?php
02 class UserController extends Zend_Controller_Action{
03         public function indexAction(){
04           $muser=new Model_User;
05           $data=$muser->listall();
06           echo "<pre>";
07           print_r($data);
08           echo "</pre>";
09      }
10 }
Đoạn code trên có tác dụng gọi model user và gọi tiếp phương thức listall() của model để hiện thị
thông tin của người dùng bởi các thẻ thử nghiệm bên dưới.

Với phương pháp tương tác này, rõ ràng chúng ta có thể chạy bất cứ câu lệnh nào mà ta muốn
trong ứng dụng một cách dễ dàng. Đồng thời, có thể tạo ra những tùy biến kết hợp giữa
Zend_Db_Table và Zend_Db. Chẳng hạn, với câu truy vấn đơn giản, ta có thể sử dụng
Zend_Db_Table để lấy giá trị. Nhưng với các câu truy vấn phức tạp đòi hỏi phải kết bảng, xử lý
nhiều, thì việc dùng cách tương tác Zend_Db lại là sử lựa chọn hiệu quả nhất.
01 <?php
02 class Model_User extends Zend_Db_Table_Abstract{
03      protected $_name="user";
04      protected $_primary="id";
05      protected $db;
06      public function __construct(){
07           $this->db=Zend_Registry::get('db');
08      }
09     public function listall(){
           $sql=$this->db->query("select * from user where level='1' order by
10
   id DESC");
11           return $sql->fetchAll();
12      }
13      public function listall2(){
14          $query=$this->select();
15           $query->where('level =?','2');
16           return $thisp>fetchAll($query);
17      }
18 }
Ở trên là một ví dụ về sự kết hợp cả hai, với listall() là phương thức sử dụng câu truy vấn thuần.
Trong khi listall2() ta sử dụng mô hình active record để lấy dữ liệu.

Kết thúc bài này, ít nhiều chúng ta đã có thể định hình và hiểu rõ hơn về cơ chế tương tác cơ sở
dữ liệu trong zend framework. Qua đó có thể vận dụng linh hoạt chúng trong thực tế để giải
quyết các vấn đề về cơ sở dữ liệu. Trong bài tiếp theo tôi sẽ hướng dẫn các bạn tìm hiểu và sử
dụng lớp Zend_Paginator để phân trang dữ liệu cho ứng dụng.
Phân trang là kỹ thuật có lẽ đã không còn xa lạ gì với những ai đã và đang viết web. Việc phân
trang sẽ giúp cho ứng dụng của bạn thao tác nhanh hơn và gọn hơn mỗi khi đổ dữ liệu ra bên
ngoài, vì thế có thể xem nó là một lớp quan trọng trong mọi ứng dụng hiện nay.

Trước hết ta thực hiện việc khởi tạo và khai báo thông tin kết nối cơ sở dữ liệu.
01 CREATE TABLE user (
02   id int(10) unsigned NOT NULL AUTO_INCREMENT,
03   username varchar(50) NOT NULL,
04   password char(32) NOT NULL,
05   level int(1) NOT NULL DEFAULT '1',
06   PRIMARY KEY (id)
07 );
08 INSERT INTO user(username,password,level) VALUES ('admin', '12345', '2');
09 INSERT INTO user(username,password,level) VALUES ('kenny', '12345', '2');
10 INSERT INTO user(username,password,level) VALUES ('jacky', '12345', '1');
11 INSERT INTO user(username,password,level) VALUES ('vivi', '12345', '1');
12 INSERT INTO user(username,password,level) VALUES ('abc', '123', '1');
13 INSERT INTO user(username,password,level) VALUES ('mimi123', '12345', '1');
14 INSERT INTO user(username,password,level) VALUES ('mimi456', '12345', '1');
15 INSERT INTO user(username,password,level) VALUES ('mimi789', '123', '1');
Kế đến ta khai báo kết nối trong file application.ini
1 resources.db.adapter = "Pdo_mysql"
2 resources.db.params.host = "localhost"
3 resources.db.params.username = "root"
4 resources.db.params.password = ""
5 resources.db.params.dbname = "qhonline"
Tại thư mục models ta tạo file user.php với nội dung bên dưới để thực hiện việc hiển thị thông
tin ra bên ngoài. (Xem lại bài tương tác với cơ sở dữ liệu với Zend_Db_Table)
1 <?php
2 class Model_User extends Zend_Db_Table_Abstract{
3      protected $_name="user";
4      protected $_primary="id";
5      public function listall(){
6          return $this->fetchAll()->toArray();
7      }
8}
Tiếp tục tại thư mục controllers ta tạo file tên UserController.php với nội dung:
01 <?php
02 class UserController extends Zend_Controller_Action{
03         public function indexAction()
04         {
05            $muser=new Model_User;
06            $paginator = Zend_Paginator::factory($muser->listall());
07            $paginator->setItemCountPerPage(3);
08            $paginator->setPageRange(3);
09            $currentPage = $this->_request->getParam('page',1);
10            $paginator->setCurrentPageNumber($currentPage);
11            $this->view->data=$paginator;
12       }
13 }
Tại controller này ta thực hiện việc cấu hình phân trang như sau:
+ Trước tiên ta nạp model user vào để gọi phương thức listall().
+ Tiếp tục ta khởi tạo lớp Zend_Paginatior và truyền tham số lấy được từ model qua. Tham số
này là một cái mảng liệt kê toàn bộ thành viên có trong bảng.
+ Kế tới ta cấu hình số lượng dữ liệu hiển thị trên trang. Cụ thể trong bài ta đang quy ước là 3
dòng dữ liệu trên 1 trang.
+ Ta cấu hình hiển thị 1 lần chỉ 3 trang.
+ Lấy trang hiện hành và mặc định sẽ là trang một.
+ Đưa tham số trang hiện hành vào phương thức setCurrentPageNumber()
+ Cuối cùng, ta đổ dữ liệu ra view.

Tiếp tục ta tạo view index.phtml tại thư mục: views/script/user/
01 <tr>
02      <td>User Id</td>
03       <td>Username</td>
04       <td>Level</td>
05 </tr>
06 <?php
07 foreach($this->data as $item)
08 {
09       echo "<tr>";
10       echo "<td align='center'>".$item['id']."</td>";
11       echo "<td align='center'>".$item['username']."</td>";
12       if($item['level'] == 1){
13           echo "<td align='center'>Member</td>";
14       }else{
15            echo "<td align='center'><font color='red'>Admin</font></td>";
16       }
17       echo "</tr>";
18 }
19 ?>
20 </table>
21 <?php
            echo $this->paginationControl($this->data, 'Sliding' ,
22
     'user/pagination.phtml');
23 ?>
Công việc của file view này là nhận dữ liệu từ controller và thực hiện việc lặp đỗ dữ liệu ra bên
ngoài bằng lệnh foreach().
Ở phần cuối ta có thêm đoạn lệnh sau:
1 <?php
           echo $this->paginationControl($this->data, 'Sliding' ,
2
    'user/pagination.phtml');
3 ?>
Đây là phần ta nạp 1 file phtml với mục đích hiển thị các liên kết tới, lùi, số trang của ứng dụng.
Tại views/scripts/user tạo file pagination.phtml như cấu hình ở trên với nội dung:
01 <?php if ($this->pageCount): ?>
02 <div class="paginationControl" align="center">
03 <?php
04     if (isset($this->previous)){
             echo '<a href="' . $this->url(array('page' => $this->previous)).
05
   '"> < Previous</a> | ';
06     }
07          foreach ($this->pagesInRange as $page){
08             if ($page != $this->current){

09                 echo '<a href="' . $this->url(array('page' => $page)). '">' .
   $page . '</a> | ';
10        }else{
11                echo $page . ' | ';
12            }
13      }
14           if (isset($this->next)){
            echo '<a href="' . $this->url(array('page' => $this->next)) .
15
   '">Next ></a>';
16        }
17   ?>
18 </div>
19 <?php endif; ?>
Sau khi hoàn tất, chạy ứng dụng ta sẽ thấy kết quả hiển thị như bên dưới.


Về mặt cơ bản thì Zend_Paginator làm công việc đưa tất cả record của câu truy vấn vào trong 1
mảng dữ liệu. Sau đó nó phân trang trực tiếp từ dữ liệu trong mảng này. Điều này trên thực tế thì
chỉ có thể đáp ứng được với mô hình dữ liệu nhỏ, vì nếu dùng với hàng trăm ngàn dòng dữ liệu
thì có lẽ việc đem chúng đổ vào mảng thôi cũng là điều không đơn giản.

Nhóm phát triển Zend Framework cũng hiểu những khó khăn từ phía người sử dụng về điều
này, nên các phiên bản sau này của zend đã hỗ trợ thêm nhiều phương thức nhằm giải quyết bài
toán này.
Đó là sử dụng thêm phương thức bên dưới với các tham số truyền vào, trước khi gọi lớp
Zend_Paginator.
1 new Zend_Paginator_Adapter_DbSelect()
Để thực hiện nó, trước hết ta thay đổi phương thức listall() trong model User như sau:
01 <?php
02 class Model_User extends Zend_Db_Table_Abstract{
03        protected $_name="user";
04        protected $_primary="id";
05        public function listall(){
06            $query=$this->select();
07             $query->from($this->_name,array('id','username','level'));
08             return $query;
09        }
10 }
Như bạn thấy, phương thức listall() của chúng ta giờ đây không còn là fetchall() nữa rồi. Mà
công việc của nó chỉ là thực hiện việc chọn bảng, chọn số lượng cột để hiển thị.

Kế tới tại UserController.php ta sửa lại như sau:
01 <?php
02 class UserController extends Zend_Controller_Action{
03        public function indexAction(){
04            $muser=new Model_User;
05             $adapter = new Zend_Paginator_Adapter_DbSelect($muser->listall());
06             $paginator = new Zend_Paginator($adapter);
07             $paginator->setItemCountPerPage(3);
08             $paginator->setPageRange(3);
09             $currentPage = $this->_request->getParam('page',1);
10             $paginator->setCurrentPageNumber($currentPage);
11             $this->view->data=$paginator;
12        }
13 }
Ta truyền phương thức listall() vào lớp Zend_Paginator_Adapter_DbSelect. Tại đó, tự nó sẽ
biết phải lấy dữ liệu như thế nào. Cuối cùng, thay vì ta dù ng Zend_Paginator::factory() thì nay ta
khởi tạo hẳn một phương thức và truyền dữ liệu mà ta đã cấu hình ở trên vào.

Chạy ứng dụng, bạn sẽ thấy kết quả giống với lúc ta dùng ở trên.
Vậy liệu chúng có khác gì không ?. Vì dẫu sao cả hai cùng làm công việc hiển thị toàn bộ dữ liệu
cơ mà ?.

Giờ bạn hãy mở file index.phtml ra và thêm vào dòng lệnh sau để xem kiến trúc bên trong mảng
của data trước khi đổ ra có gì nhé.
1 <?php
2             echo "<pre>";
3          print_r($this->data);
4          echo "</pre>";
5 ?>
Và kết quả thật sự bất ngờ phải không nào, trong mảng dữ liệu của chúng ta hoàn toàn không có
dòng nào liên quan đến dữ liệu có trong bảng cả. Vậy Zend_Paginator tự hiểu và tự giới hạn dữ
liệu trả về giúp cho chúng ta. Ngay trên manual của Zend Framework cũng nhấn mạnh về điều
này khi bạn sử dụng thêm lớp Zend_Paginator_Adapter_DbSelect().

Additionally these adapters do not fetch all records from the database in order to count them.
Instead, the adapters manipulates the original query to produce the corresponding COUNT
query. Paginator then executes that COUNT query to get the number of rows.This does require
an extra round-trip to the database, but this is many times faster than fetching an entire
result set and using count(). Especially with large collections of data.

Phần bôi đen màu đỏ là phần tôi muốn các bạn chú ý khi tham khảo đoạn thông tin trên từ
manual của Zend Framework.

Tải toàn bộ mã nguồn của bài học tại đây

Như vậy, qua phần này. Tôi đã hướng dẫn các bạn bước đầu làm quen và tìm hiểu được lớp
Zend_Paginator, từ đó sử dụng chúng cho công việc phân trang dữ liệu trong ứng dụng. Tiếp
tục ở bài sau, chúng ta sẽ cùng tìm hiểu về lớp Zend_Form, đồng thời dùng nó để xây dựng các
biểu mẫu nhập liệu như thế nào.

More Related Content

What's hot

Ebook oracle-thuc-hanh-nguyen-huu-trong
Ebook oracle-thuc-hanh-nguyen-huu-trongEbook oracle-thuc-hanh-nguyen-huu-trong
Ebook oracle-thuc-hanh-nguyen-huu-trong
ngobacuong
 
Hỏi tình hình bk tiny bktiny-hdsd
Hỏi tình hình bk tiny   bktiny-hdsdHỏi tình hình bk tiny   bktiny-hdsd
Hỏi tình hình bk tiny bktiny-hdsd
Vu Hung Nguyen
 

What's hot (20)

Bài 2 Làm quen với môi trường PHP và MySQL (phần 2) - Giáo trình FPT
Bài 2 Làm quen với môi trường PHP và MySQL (phần 2) - Giáo trình FPTBài 2 Làm quen với môi trường PHP và MySQL (phần 2) - Giáo trình FPT
Bài 2 Làm quen với môi trường PHP và MySQL (phần 2) - Giáo trình FPT
 
Bài 2 Các kỹ thuật lập trình MySQL với PHP nâng cao - Xây dựng ứng dụng web
Bài 2 Các kỹ thuật lập trình MySQL với PHP nâng cao - Xây dựng ứng dụng webBài 2 Các kỹ thuật lập trình MySQL với PHP nâng cao - Xây dựng ứng dụng web
Bài 2 Các kỹ thuật lập trình MySQL với PHP nâng cao - Xây dựng ứng dụng web
 
Giáo trình Zend Framework 2.0 - Nhúng template vào ứng dung ZF2 (P3) - Bài 7
Giáo trình Zend Framework 2.0 - Nhúng template vào ứng dung ZF2 (P3) - Bài 7Giáo trình Zend Framework 2.0 - Nhúng template vào ứng dung ZF2 (P3) - Bài 7
Giáo trình Zend Framework 2.0 - Nhúng template vào ứng dung ZF2 (P3) - Bài 7
 
Web301 slide 2
Web301   slide 2Web301   slide 2
Web301 slide 2
 
Web3012 slide 8
Web3012   slide 8Web3012   slide 8
Web3012 slide 8
 
Web201 slide 1
Web201   slide 1Web201   slide 1
Web201 slide 1
 
tao module joomla 1.5
tao module  joomla 1.5tao module  joomla 1.5
tao module joomla 1.5
 
Web201 slide 4
Web201   slide 4Web201   slide 4
Web201 slide 4
 
Wp hoi-thao-phan-quyen
Wp hoi-thao-phan-quyenWp hoi-thao-phan-quyen
Wp hoi-thao-phan-quyen
 
Web201 slide 3
Web201   slide 3Web201   slide 3
Web201 slide 3
 
Bài 7 Xây dựng website sử dụng PHP và MySQL - Giáo trình FPT
Bài 7 Xây dựng website sử dụng PHP và MySQL - Giáo trình FPTBài 7 Xây dựng website sử dụng PHP và MySQL - Giáo trình FPT
Bài 7 Xây dựng website sử dụng PHP và MySQL - Giáo trình FPT
 
Lap trinh-joomla-15-theo-mo-hinh-mvc
Lap trinh-joomla-15-theo-mo-hinh-mvcLap trinh-joomla-15-theo-mo-hinh-mvc
Lap trinh-joomla-15-theo-mo-hinh-mvc
 
Bài 4 Lập trình PHP (phần 2) - Giáo trình FPT
Bài 4 Lập trình PHP (phần 2) - Giáo trình FPTBài 4 Lập trình PHP (phần 2) - Giáo trình FPT
Bài 4 Lập trình PHP (phần 2) - Giáo trình FPT
 
Web201 slide 5
Web201   slide 5Web201   slide 5
Web201 slide 5
 
Ebook oracle-thuc-hanh-nguyen-huu-trong
Ebook oracle-thuc-hanh-nguyen-huu-trongEbook oracle-thuc-hanh-nguyen-huu-trong
Ebook oracle-thuc-hanh-nguyen-huu-trong
 
Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)
 
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPTBài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
 
Hướng dẫn lập trình với SCSF phần II(smart client software factory)
Hướng dẫn lập trình với SCSF phần II(smart client software factory)Hướng dẫn lập trình với SCSF phần II(smart client software factory)
Hướng dẫn lập trình với SCSF phần II(smart client software factory)
 
Hỏi tình hình bk tiny bktiny-hdsd
Hỏi tình hình bk tiny   bktiny-hdsdHỏi tình hình bk tiny   bktiny-hdsd
Hỏi tình hình bk tiny bktiny-hdsd
 
Bài 4 Bảo mật cho website - Xây dựng ứng dụng web
Bài 4 Bảo mật cho website - Xây dựng ứng dụng webBài 4 Bảo mật cho website - Xây dựng ứng dụng web
Bài 4 Bảo mật cho website - Xây dựng ứng dụng web
 

Similar to All zend

Tutoria mvc framework
Tutoria mvc frameworkTutoria mvc framework
Tutoria mvc framework
Xuan Le
 
php với oracle database
php với oracle databasephp với oracle database
php với oracle database
Ngo Trung
 
Giao trinh asp.ne_tvoi_csharp
Giao trinh asp.ne_tvoi_csharpGiao trinh asp.ne_tvoi_csharp
Giao trinh asp.ne_tvoi_csharp
ngohanty13
 
Lap trinhcosodulieuvoi c-sharp_phan-1
Lap trinhcosodulieuvoi c-sharp_phan-1Lap trinhcosodulieuvoi c-sharp_phan-1
Lap trinhcosodulieuvoi c-sharp_phan-1
Hiển Phùng
 
My sql part 2 - manager mysql server - backup & restore database
My sql   part 2 - manager mysql server - backup & restore databaseMy sql   part 2 - manager mysql server - backup & restore database
My sql part 2 - manager mysql server - backup & restore database
laonap166
 

Similar to All zend (20)

TÀI LIỆU HƯỚNG VIẾT MODULE VÀ WEBSERVICE CHO MAGENTO 1.7
TÀI LIỆU HƯỚNG VIẾT MODULE VÀ WEBSERVICE CHO MAGENTO 1.7TÀI LIỆU HƯỚNG VIẾT MODULE VÀ WEBSERVICE CHO MAGENTO 1.7
TÀI LIỆU HƯỚNG VIẾT MODULE VÀ WEBSERVICE CHO MAGENTO 1.7
 
Yii
YiiYii
Yii
 
Laravel 5 framework
Laravel 5 frameworkLaravel 5 framework
Laravel 5 framework
 
Bài 1 Lập trình website theo mô hình MVC - Xây dựng ứng dụng web
Bài 1 Lập trình website theo mô hình MVC - Xây dựng ứng dụng webBài 1 Lập trình website theo mô hình MVC - Xây dựng ứng dụng web
Bài 1 Lập trình website theo mô hình MVC - Xây dựng ứng dụng web
 
Web301 slide 1
Web301   slide 1Web301   slide 1
Web301 slide 1
 
Asp.net mvc 3 (c#) (9 tutorials) egroups vn
Asp.net mvc 3 (c#) (9 tutorials)   egroups vnAsp.net mvc 3 (c#) (9 tutorials)   egroups vn
Asp.net mvc 3 (c#) (9 tutorials) egroups vn
 
Asp control
Asp controlAsp control
Asp control
 
Asp.net mvc framework qua cac vi du
Asp.net mvc framework  qua cac vi duAsp.net mvc framework  qua cac vi du
Asp.net mvc framework qua cac vi du
 
Co ban ve_zend_framework 1
Co ban ve_zend_framework 1Co ban ve_zend_framework 1
Co ban ve_zend_framework 1
 
Tutoria mvc framework
Tutoria mvc frameworkTutoria mvc framework
Tutoria mvc framework
 
Aspnet 3.5 _04
Aspnet 3.5 _04Aspnet 3.5 _04
Aspnet 3.5 _04
 
Aspnet 3.5 -06
Aspnet 3.5 -06Aspnet 3.5 -06
Aspnet 3.5 -06
 
Bao cao thuc tap tuan 5
Bao cao thuc tap tuan 5Bao cao thuc tap tuan 5
Bao cao thuc tap tuan 5
 
php với oracle database
php với oracle databasephp với oracle database
php với oracle database
 
Asp net mvc3 music store egroups vn
Asp net mvc3 music store   egroups vnAsp net mvc3 music store   egroups vn
Asp net mvc3 music store egroups vn
 
Tìm hiểu về Joomla
Tìm hiểu về Joomla Tìm hiểu về Joomla
Tìm hiểu về Joomla
 
Giao trinh asp.ne_tvoi_csharp
Giao trinh asp.ne_tvoi_csharpGiao trinh asp.ne_tvoi_csharp
Giao trinh asp.ne_tvoi_csharp
 
Lap trinhcosodulieuvoi c-sharp_phan-1
Lap trinhcosodulieuvoi c-sharp_phan-1Lap trinhcosodulieuvoi c-sharp_phan-1
Lap trinhcosodulieuvoi c-sharp_phan-1
 
My sql part 2 - manager mysql server - backup & restore database
My sql   part 2 - manager mysql server - backup & restore databaseMy sql   part 2 - manager mysql server - backup & restore database
My sql part 2 - manager mysql server - backup & restore database
 
Asp.net 3.5 _1
Asp.net 3.5 _1Asp.net 3.5 _1
Asp.net 3.5 _1
 

Recently uploaded

Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptxBài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
DungxPeach
 
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoiC6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
dnghia2002
 
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdfxemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
Xem Số Mệnh
 
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
ChuThNgnFEFPLHN
 
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdfSLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
hoangtuansinh1
 

Recently uploaded (20)

Giáo trình nhập môn lập trình - Đặng Bình Phương
Giáo trình nhập môn lập trình - Đặng Bình PhươngGiáo trình nhập môn lập trình - Đặng Bình Phương
Giáo trình nhập môn lập trình - Đặng Bình Phương
 
xemsomenh.com-Vòng Thái Tuế và Ý Nghĩa Các Sao Tại Cung Mệnh.pdf
xemsomenh.com-Vòng Thái Tuế và Ý Nghĩa Các Sao Tại Cung Mệnh.pdfxemsomenh.com-Vòng Thái Tuế và Ý Nghĩa Các Sao Tại Cung Mệnh.pdf
xemsomenh.com-Vòng Thái Tuế và Ý Nghĩa Các Sao Tại Cung Mệnh.pdf
 
các nội dung phòng chống xâm hại tình dục ở trẻ em
các nội dung phòng chống xâm hại tình dục ở trẻ emcác nội dung phòng chống xâm hại tình dục ở trẻ em
các nội dung phòng chống xâm hại tình dục ở trẻ em
 
Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptxBài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
Bài tập nhóm Kỹ Năng Gỉai Quyết Tranh Chấp Lao Động (1).pptx
 
Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hộiTrắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
Trắc nghiệm CHƯƠNG 5 môn Chủ nghĩa xã hội
 
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoiC6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
C6. Van de dan toc va ton giao ....pdf . Chu nghia xa hoi
 
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
ĐỀ KIỂM TRA CUỐI KÌ 2 BIÊN SOẠN THEO ĐỊNH HƯỚNG ĐỀ BGD 2025 MÔN TOÁN 10 - CÁN...
 
Danh sách sinh viên tốt nghiệp Đại học - Cao đẳng Trường Đại học Phú Yên năm ...
Danh sách sinh viên tốt nghiệp Đại học - Cao đẳng Trường Đại học Phú Yên năm ...Danh sách sinh viên tốt nghiệp Đại học - Cao đẳng Trường Đại học Phú Yên năm ...
Danh sách sinh viên tốt nghiệp Đại học - Cao đẳng Trường Đại học Phú Yên năm ...
 
TÀI LIỆU BỒI DƯỠNG HỌC SINH GIỎI KỸ NĂNG VIẾT ĐOẠN VĂN NGHỊ LUẬN XÃ HỘI 200 C...
TÀI LIỆU BỒI DƯỠNG HỌC SINH GIỎI KỸ NĂNG VIẾT ĐOẠN VĂN NGHỊ LUẬN XÃ HỘI 200 C...TÀI LIỆU BỒI DƯỠNG HỌC SINH GIỎI KỸ NĂNG VIẾT ĐOẠN VĂN NGHỊ LUẬN XÃ HỘI 200 C...
TÀI LIỆU BỒI DƯỠNG HỌC SINH GIỎI KỸ NĂNG VIẾT ĐOẠN VĂN NGHỊ LUẬN XÃ HỘI 200 C...
 
xemsomenh.com-Vòng Lộc Tồn - Vòng Bác Sĩ và Cách An Trong Vòng Lộc Tồn.pdf
xemsomenh.com-Vòng Lộc Tồn - Vòng Bác Sĩ và Cách An Trong Vòng Lộc Tồn.pdfxemsomenh.com-Vòng Lộc Tồn - Vòng Bác Sĩ và Cách An Trong Vòng Lộc Tồn.pdf
xemsomenh.com-Vòng Lộc Tồn - Vòng Bác Sĩ và Cách An Trong Vòng Lộc Tồn.pdf
 
Access: Chuong III Thiet ke truy van Query.ppt
Access: Chuong III Thiet ke truy van Query.pptAccess: Chuong III Thiet ke truy van Query.ppt
Access: Chuong III Thiet ke truy van Query.ppt
 
Kiến thức cơ bản về tư duy số - VTC Net Viet
Kiến thức cơ bản về tư duy số - VTC Net VietKiến thức cơ bản về tư duy số - VTC Net Viet
Kiến thức cơ bản về tư duy số - VTC Net Viet
 
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdfxemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
xemsomenh.com-Vòng Tràng Sinh - Cách An 12 Sao Và Ý Nghĩa Từng Sao.pdf
 
BỘ LUYỆN NGHE VÀO 10 TIẾNG ANH DẠNG TRẮC NGHIỆM 4 CÂU TRẢ LỜI - CÓ FILE NGHE.pdf
BỘ LUYỆN NGHE VÀO 10 TIẾNG ANH DẠNG TRẮC NGHIỆM 4 CÂU TRẢ LỜI - CÓ FILE NGHE.pdfBỘ LUYỆN NGHE VÀO 10 TIẾNG ANH DẠNG TRẮC NGHIỆM 4 CÂU TRẢ LỜI - CÓ FILE NGHE.pdf
BỘ LUYỆN NGHE VÀO 10 TIẾNG ANH DẠNG TRẮC NGHIỆM 4 CÂU TRẢ LỜI - CÓ FILE NGHE.pdf
 
TUYỂN TẬP 50 ĐỀ LUYỆN THI TUYỂN SINH LỚP 10 THPT MÔN TOÁN NĂM 2024 CÓ LỜI GIẢ...
TUYỂN TẬP 50 ĐỀ LUYỆN THI TUYỂN SINH LỚP 10 THPT MÔN TOÁN NĂM 2024 CÓ LỜI GIẢ...TUYỂN TẬP 50 ĐỀ LUYỆN THI TUYỂN SINH LỚP 10 THPT MÔN TOÁN NĂM 2024 CÓ LỜI GIẢ...
TUYỂN TẬP 50 ĐỀ LUYỆN THI TUYỂN SINH LỚP 10 THPT MÔN TOÁN NĂM 2024 CÓ LỜI GIẢ...
 
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
SD-05_Xây dựng website bán váy Lolita Alice - Phùng Thị Thúy Hiền PH 2 7 8 6 ...
 
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdfSLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
SLIDE - Tu van, huong dan cong tac tuyen sinh-2024 (đầy đủ chi tiết).pdf
 
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
20 ĐỀ DỰ ĐOÁN - PHÁT TRIỂN ĐỀ MINH HỌA BGD KỲ THI TỐT NGHIỆP THPT NĂM 2024 MÔ...
 
Bài học phòng cháy chữa cháy - PCCC tại tòa nhà
Bài học phòng cháy chữa cháy - PCCC tại tòa nhàBài học phòng cháy chữa cháy - PCCC tại tòa nhà
Bài học phòng cháy chữa cháy - PCCC tại tòa nhà
 
TUYỂN TẬP ĐỀ THI GIỮA KÌ, CUỐI KÌ 2 MÔN VẬT LÍ LỚP 11 THEO HÌNH THỨC THI MỚI ...
TUYỂN TẬP ĐỀ THI GIỮA KÌ, CUỐI KÌ 2 MÔN VẬT LÍ LỚP 11 THEO HÌNH THỨC THI MỚI ...TUYỂN TẬP ĐỀ THI GIỮA KÌ, CUỐI KÌ 2 MÔN VẬT LÍ LỚP 11 THEO HÌNH THỨC THI MỚI ...
TUYỂN TẬP ĐỀ THI GIỮA KÌ, CUỐI KÌ 2 MÔN VẬT LÍ LỚP 11 THEO HÌNH THỨC THI MỚI ...
 

All zend

  • 1. Xây dựng mô hình các thư mục như sau: www/zfexam/application www/zfexam/public/ www/zfexam/library Tại thư mục library, bạn chỉ việc copy và thư viện zend, phiên bản mới nhất vào đây. Thư mục pubic: bạn lần lượt tạo 2 file mới là: index.php và .htaccess File index với nội dung như sau: 01 <?php 02 defined('APPLICATION_PATH') 03 || define('APPLICATION_PATH', 04 realpath(dirname(__FILE__) . '/../application')); 05 defined('APPLICATION_ENV') 06 || define('APPLICATION_ENV', 07 (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') 08 : 'production')); 09 set_include_path(implode(PATH_SEPARATOR, array( 10 dirname(dirname(__FILE__)) . '/library', 11 get_include_path(), 12 ))); 13 require_once 'Zend/Application.php' ; 14 $application = new Zend_Application( 15 APPLICATION_ENV, 16 APPLICATION_PATH . '/configs/application.ini' 17 ); 18 $application->bootstrap()->run(); Trong file .htaccess lại tiếp tục copy và past đoạn code sau: 1 RewriteEngine On 2 RewriteCond %{REQUEST_FILENAME} -s [OR] 3 RewriteCond %{REQUEST_FILENAME} -l [OR] 4 RewriteCond %{REQUEST_FILENAME} -d 5 RewriteRule ^.*$ - [NC,L] 6 RewriteRule ^.*$ index.php [NC,L] Tại thư mục application bạn lại tạo các thư mục: www/zfexam/application/controllers www/zfexam/application/views www/zfexam/application/models
  • 2. www/zfexam/application/configs Tại thư mục controllers tạo file: www/zfexam/application/controllers/IndexController.php Tại file IndexController.php copy nội dung sau: 1 <?php 2 class IndexController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 } 5} 6 ?> Tại thư mục views tạo thư mục: www/zfexam/application/views/scripts/index/index.phtml File index/index.phtml có nội dung như sau: 1 <h1>hello Zend Framework</h1> Tại thư mục configs tạo file application.ini: www/zfexam/application/configs/application.ini Với nội dung: [production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" Và tiếp tục tạo file bootstrap.php ở thư mục application www/zfexam/application/bootstrap.php Với nội dung: 1 <?php 2 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{ 3} Và cuối cùng chúng ta cùng chạy: http://localhost/zfexam/public/ Như vậy, bạn đã viết ứng dụng đầu tiên bằng Zend Framework rồi đấy.
  • 3. Và cấu trúc Zend Framework như hình bên dưới: Lưu ý : Để zend framework, bạn cần phải bật mod rewrite trên web server. Cách bật mod rewrite: Đầu tiên bạn cần tìm đến file httpd.conf (vì không biết các sử dụng web server nào nên tôi không đưa ra đường dẫn cụ thể). Các bạn cũng có thể dùng chế độ tìm kiếm file trong window để tìm file này. Sau đó tìm đến dòng LoadModule rewrite_module modules/mod_rewrite.so Và bỏ đi dấu thăng của nó nếu máy của bạn vẫn chưa bật mod rewrite. Cuối cùng bạn cẩn restart lại apache để hệ thống cập nhật thông tin mà bạn vừa chỉnh sửa từ hệ thống. Ví dụ xét liên kết:
  • 4. http://qhonline.info/book/viewbook/ Như vậy book được xem là một controller và viewbook được xem là một action của controller đó. Khi hoạt động, trong controller bạn sẽ khởi tạo những action như mong muốn thông qua việc thiết lập phương thức một cách cụ thể. Ví dụ: 1 <?php 2 class IndexController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 } 5} Như vậy IndexController cho ta Controller mang tên index và indexAction cho ta action là index. Khi đó bạn bắt buộc phải khởi tạo trong views một thư mục ứng với controller là index trong scripts. Và file index.phml ứng với action là index. Xét ví dụ khác: 1 <?php 2 class BookController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 } 5 public function viewbookAction(){ 6 } 7} Ở ví dụ này cho ta biết Controller là Book, 2 action là index và viewbook. Như vậy, để chạy được ứng dụng. Bạn cần tạo thư mục Book trong views ứng với controller và file index.phtml, viewbook.phtml. Cụ thể: application/controller/BookController.php application/views/scripts/Book/index.phtml application/views/scripts/Book/viewbook.phtml B- Tìm hiểu nội dung file index.php và application.ini trong Zend Framework: Nội dung đầy đủ file index.php 01 <?php 02 defined('APPLICATION_PATH') 03 || define('APPLICATION_PATH', 04 realpath(dirname(__FILE__) . '/../application'));
  • 5. 05 defined('APPLICATION_ENV') 06 || define('APPLICATION_ENV', 07 (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') 08 : 'production')); 09 set_include_path(implode(PATH_SEPARATOR, array( 10 dirname(dirname(__FILE__)) . '/library', 11 get_include_path(), 12 ))); 13 require_once 'Zend/Application.php' ; 14 $application = new Zend_Application( 15 APPLICATION_ENV, 16 APPLICATION_PATH . '/configs/application.ini' 17 ); 18 $application->bootstrap()->run(); Tiếp theo chúng ta sẽ tìm hiểu xem bên trong file index.php này có những điểm gì cần lưu ý. 1 defined('APPLICATION_PATH') 2 || define('APPLICATION_PATH', 3 realpath(dirname(__FILE__) . '/../application')); Dòng này khai báo cho Zend Framework biết bạn đang đặt thư mục application ở đâu thông qua một hằng APPLICATION_PATH. Đây là hằng mà bạn sẽ dùng rất nhiều trong các khai báo cấu hình sau này. 1 defined('APPLICATION_ENV') 2 || define('APPLICATION_ENV', 3 (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') 4 : 'production')); Dòng này cho phép đọc thông tin phân đoạn có tên production ở file application.ini ở bên dưới. Và ta đưa chữ production vào một hằng là APPLICATION_ENV. 1 set_include_path(implode(PATH_SEPARATOR, array( 2 dirname(dirname(__FILE__)) . '/library', 3 get_include_path(), 4 ))); Dòng này làm nhiệm vụ load nội dung của thư viện library nơi mà bạn chứa thư viện của zend. Nôm na có thể hiểu là, nếu bạn sử dụng dòng này. Thì ở phần dưới và những trang khác, thay vì bạn phải gõ: require_once 'Library/Zend/Application.php' Thì giờ bạn chỉ cần gõ: require_once 'Zend/Application.php' . Vì mặc định thư viện đã được nạp vào rồi. 1 require_once 'Zend/Application.php' ; 2 $application = new Zend_Application( 3 APPLICATION_ENV, 4 APPLICATION_PATH . '/configs/application.ini' 5 ); Tiếp tới, chúng ta nạp nội dung trang Application.php và tiếp tục gọi trang application.ini ở thư mục config. Và nếu bạn chú ý, sẽ thấy chúng ta sử dụng 2 hằng vừa khởi tạo là APPLICATION_ENV và APPLICATION_PATH để lấy thông tin.
  • 6. 1 $application->bootstrap()->run(); Và cuối cùng là việc thực thi lệnh bằng hàm run(). Khi chúng ta đã hiểu được vấn đề, thì chúng ta có thể viết chúng gọn lại theo cách mà ta hiểu. 01 <?php 02 define('APPLICATION_PATH', 03 realpath(dirname(__FILE__) . '/../application')); 04 define('APPLICATION_ENV','production'); 05 set_include_path(dirname(dirname(__FILE__)) . '/library'); 06 require_once 'Zend/Application.php' ; 07 $application = new Zend_Application( 08 APPLICATION_ENV, 09 APPLICATION_PATH . '/configs/application.ini' 10 ); 11 $application->bootstrap()->run(); Tiếp tới ta tìm hiểu file application.ini để xem nó thể hiện thông tin gì: 1 [production] 2 phpSettings.display_startup_errors = 0 3 phpSettings.display_errors = 0 4 bootstrap.path = APPLICATION_PATH "/Bootstrap.php" 5 bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH 6 "/controllers" Dòng đầu tiên có chức năng khởi tạo phân đoạn mang giá trị [production]. Bởi vì trong file này chúng ta chia làm nhiều phân đoạn một cách rõ ràng. Ví dụ phân đoạn chứa cơ sở dữ liệu, phân đoạn chứa thông tin layout, kết nối CSDL,…. 1 [production] 2 phpSettings.display_startup_errors = 0 3 phpSettings.display_errors = 0 Hai dòng này cho phép bạn có bật tính năng báo lỗi của ZEND FRAMEWORK hay không, nếu có bạn sẽ sửa giá trị thành 1. 1 bootstrap.path = APPLICATION_PATH "/Bootstrap.php" 2 bootstrap.class = "Bootstrap" Hai dòng này cho phép bạn tìm tới file bootstrap.php để thông qua nó tương tác các thư viện hàm trong ZEND FRAMEWORK. Đồng thời chỉ định tên gọi của class là Bootstrap. Ở đây bạn cũng cần lưu ý là tên class trong file Bootstrap.php phải cùng tên với Bootstrap mà bạn đã khai báo ở application.ini. resources.frontController.controllerDirectory = APPLICATION_PATH 1 "/controllers" Dòng này chỉ ra đường dẫn tới thư mục controllers trong thư mục application của chúng ta.
  • 7. Trước tiên, ta xét lại cấu trúc mặc định của hệ thống qua tấm hình bên dưới: Như chúng ta thấy, với cấu hình ở trên thì trong application có 3 thư mục chủ đạo là controllers, models, views. Vậy để tạo ứng dụng theo mô hình module ta tạo 1 thư mực modules. Trong thư mục này ta tạo tiếp 2 module là default và admin theo cấu trúc: zf2/application/modules/default zf2/application/modules/admin Tại mỗi module default và admin ta lại tạo tiếp 3 thư mục con là controllers, models, views. Theo cấu trúc. Module default: zf2/application/modules/default/controllers zf2/application/modules/default/models zf2/application/modules/default/views Module admin: zf2/application/modules/admin/controllers zf2/application/modules/admin/models zf2/application/modules/admin/views
  • 8. Tại các thư mục controllers này lần lượt tạo các file tên IndexController.php với nội dung như sau: File IndexController.php của module default 1 <?php 2 class IndexController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 } 5 6} File IndexController.php của module admin 1 <?php 2 class Admin_IndexController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 } 5 6} Nếu để ý kỹ, chúng ta có thể thấy rằng trước tên mỗi class ta lại thêm tên module của chúng ở trước. Đây là kỹ thuật lazy loading trong OOP, được sử dụng để triệu nạp file controller trong từng module của zend framework. Riêng đối với module default là module mặc định nên trong class controller ta không cần khai báo thêm tên module giống với module admin. Tiếp tục, ta di chuyển 2 file index.php và .htaccess ra khỏi thư mục public theo cấu trúc như sau: www/zf2/index.php www/zf2/.htaccess Vì chúng ta đã di chuyển file index.php ra khỏi thư mục public và nó ngang cấp với thư mục application nên lúc này đường dẫn triệu nạp trong file cũng sẽ thay đổi. File index.php cũ của chúng ta: 01 <?php 02 define('APPLICATION_PATH', 03 realpath(dirname(__FILE__) . '/../application')); 04 define('APPLICATION_ENV','production'); 05 set_include_path(dirname(dirname(__FILE__)) . '/library'); 06 require_once 'Zend/Application.php' ; 07 $application = new Zend_Application( 08 APPLICATION_ENV, 09 APPLICATION_PATH . '/configs/application.ini' 10 ); 11 $application->bootstrap()->run();
  • 9. Vì giờ file index.php đã đưa ra ngoài public. Nên chắc chắn đường dẫn vào thư mục application sẽ thay đổi. Khi đó sẽ là: realpath(dirname(__FILE__) . '/application'); Vậy hằng APPLICATION_PATH cũng chúng ta đã thay đổi và trỏ đường dẫn tới thư mục application. Tiếp tục ta cấu hình cho ứng dụng tìm tới được thư mục library. set_include_path(APPLICATION_PATH . '/../library'); Bạn hiểu thế nào về đoạn cấu hình này ?. Vì hằng APPLICATION_PATH ở trên đã có thể tìm thấy được thư mục application. Cho nên từ thư mục ấy ta back trở ra để tìm tới thư mục library. Vì thế trước library ta có dùng "/../library" là vì vậy. Vậy file index.php củng chúng ta sau khi chỉnh sửa sẽ như sau: 01 <?php 02 define('APPLICATION_PATH', 03 realpath(dirname(__FILE__) . '/application')); 04 define('APPLICATION_ENV','production'); 05 set_include_path(APPLICATION_PATH . '/../library'); 06 require_once 'Zend/Application.php' ; 07 $application = new Zend_Application( 08 APPLICATION_ENV, 09 APPLICATION_PATH . '/configs/application.ini' 10 ); 11 $application->bootstrap()->run(); Tiếp tục ta tạo file index.phtml trong từng thư mục views của từng module. www/zf2/application/modules/default/views/scripts/index/index.phtml 1 <h1>Hello Zend Framework – Default Module<h1> www/zf2/application/modules/admin/views/scripts/index/index.phtml 1 <h1>Hello Zend Framework – Admin Module<h1> Chạy thử ứng dụng xem nào: http://localhost/zf2/default http://localhost/zf2/admin/index
  • 10. Bị lỗi rồi phải không nào ?. Ứng dụng bị lỗi là vì chúng ta vẫn chưa cấu hình để tìm thấy được thư mục module. Vì thế, để giải quyết. Tả mở file application.ini trong thư mục configs ra và thêm vào 2 dòng sau: 1 resources.frontController.moduleDirectory=APPLICATION_PATH "/modules" 2 resources.modules="" Dòng ở trên làm gì vậy ?. Câu trả lời nó chỉ ra đường dẫn tới thư mục modules của chúng ta. Và dòng thứ 2 chỉ ra ta đang gọi cơ chế module autoload. Khi đó các class, model, form,… sẽ được tự động nạp vào từng module của chúng ta. Chạy xem lại xem nào. Kết quả sẽ như thế này đây Hình ảnh cấu trúc multi Module trong Zend Framework (file .htaccess không hiển thị trong mô hình cây này).
  • 11. A- Tìm hiểu quy tắc hoạt động của Zend View Trong controller của zend framework khi chúng ta khởi tạo một action (hành động). Thì tương đương tại thư mục views/scripts/tên_controller/hành_động.phtml. Ví dụ: Nếu là NewsController và addAction() thì chúng ta sẽ tạo view theo cấu trúc: Views/scripts/news/add.phtml Như vậy, Zend Framework sẽ tự động gọi views của action add khi người dùng tham chiếu tới action add qua đường dẫn. Vậy những gì mà chúng ta trình bày ở view add.phtml sẽ hiển thị cho người dùng thấy khi họ tham chiếu tới action add. Vậy để truyền tham số mà chúng ta thao tác ở controller cho view như thế nào ?. Zend Framework cho phép người sử dụng truyền tham số thông qua phương thức: $this->view->tên_biến; Và tại các file view có đuôi .phtml chúng ta chỉ cần sử dụng cú pháp: $this->tên_biến để lấy giá trị mà chúng ta đang truyền từ controller. Ví dụ ta tạo controller tên: IndexController.php với nội dung: 1 <?php 2 class IndexController extends Zend_Controller_Action { 3 public function indexAction(){ 4 $this->view->string= "hello Zend Framework – QHOnline.Info"; 5 } 6 7} Tại thư mục views/scripts/index ta tạo file tên index.phtml với nội dung: 1 <?php 2 echo "<h1>".$this->string."</h1>"; 3 ?> Và kết quả sẽ ra là: Hello Zend Framework – QHOnline.Info Như bạn thấy ta có thể truyền tham số và nhận tham số dễ dàng tại view với quy tắc ở trên phải không nào. Trường hợp truyền một mảng thì có cách truyền như sau: 01 <?php 02 class IndexController extends Zend_Controller_Action{
  • 12. 03 public function indexAction() { 04 $data= array( 05 'title' => 'Zend Framework', 06 'author'=> 'Kenny', 07 'date' => '20-11-2009', 08 'website'=> 'www.QHOnline.Info' 09 ); 10 $this->view->info =$data; 11 } 12 } Tại file view ta viết lại như sau: 1 <?php 2 foreach($this->info as $k => $v) 3{ 4 echo "<b>$k</b>: $v<br />"; 5} 6 ?> Chạy thử nghiệm: http://localhost/zfexample/index/index Kết quả: dữ liệu của mảng sẽ được hiển thị như mong đợi. Trong trường hợp, chúng ta không muốn action phải gọi view thì tại action trong controller mà ta muốn, thêm vào phương thức sau: $this->getHelper('viewRenderer')->setNoRender(); Khi sử dụng phương thức này thì tại action đó ta không cần phải tạo file trong thư mục views. Vì nó bỏ qua việc render file view của action. B- Nạp 1 file khác trong view như thế nào ? Để thực hiện việc nạp 1 file khác vào view trong zend framework. Chúng ta có thể gọi trong view thông qua phương thức: echo $this->render("Tên_file.phtml"); Lưu ý là file của chúng ta phải lưu trong thư mục views/scripts/. Vì mặc định trong zend view các file xử lý sẽ nằm tại thư mục views/scripts/ Ví dụ: Tạo action demo trong IndexController với nội dung như sau: 1 <?php 2 class IndexController extends Zend_Controller_Action{ 3 function demoAction(){ 4 $this->view->hello="Hello Zend Framework - QHOnline.Info";
  • 13. 5 } 6} Tạo tiếp file demo.phtml trong thư mục views/scripts/index/ 1 <?php 2 echo "<h1>".$this->hello."</h1>"; 3 echo $this->render("qhonline.phtml"); 4 ?> Tạo tiếp file qhonline.phtml trong thư mục: views/scripts 1 <h2>Khoa hoc PHP Online Version 2.0</h2> Chạy thử nghiệm: http://localhost/zfexample/index/demo Kết quả: dữ liệu trả về với nội dung như mong đợi. C- Thiết lập thông tin cơ bản trong zend view: Zend view hỗ trợ người dùng những thư viện cấu hình cơ bản trong HTML như <title>, <link>, <script>,… Như vậy để sử dụng được chúng ta cần thiết lập chúng thông qua các controller và từ nó đổ tham số ra view. a) Thiết lập chuẩn XHTML: Cú pháp: doctype("Tham số") Tham số chính là những chuẩn mà chúng ta mong muốn. b) Thiết lập CSS: Cú pháp: appendStylesheet(URL,Định dạng, Điều kiện) Tương đương: <link href="URL" media="??" /> c) Thiết lập thẻ Title: Cú pháp: headtitle("Tieu de") Tương đương: <title> Tieu de </title> d) Thiết lập thẻ Meta: Cú pháp: appendName("keyword","Zend Framework,"); Trường hợp thêm description ta có:
  • 14. offsetSetName("1","description","Khoa hoc PHP Framework tai QHOnline") Tham số đầu là vị trí, tham số sau là tên description và tham số thứ 3 là thông tin. e) Thiết lập thẻ script: Cú pháp: appendFile(URL,"text/javascript") Trường hợp nạp file js thứ 2 offsetSetFile("1","URL","text/javascript") Ví dụ: Tạo testAction() trong controller index với nội dung: 01 function testAction(){ 02 $baseurl=$this->_request->getbaseurl(); 03 $this->view->doctype(); 04 $this->view->headtitle("QHOnline.Info - Chapter 3: Zend Framework"); $this->view->headMeta()->appendName("keyword","Zend 05 Framework,Codeigniter,PHP Framework"); $this->view->headMeta()->offsetSetName("1","description","Khoa hoc PHP 06 Framework tai QHOnline"); $this->view->headLink()- 07 >appendStylesheet($baseurl."/public/css/test.css"); $this->view->headscript()- 08 >appendFile($baseurl."/public/js/test.js","text/javascript"); $this->view->headscript()- 09 >offsetSetFile("1",$baseurl."/public/js/test2.js","text/javascrip 10 } Tạo tiếp file test.phtml tại thư mục: views/scripts/index với nội dung: 01 <?php echo $this->doctype() ?> 02 <html> 03 <head> 04 <?php echo $this->headTitle() ?> 05 <?php echo $this->headMeta() ?> 06 <?php echo $this->headLink() ?> 07 <?php echo $this->headScript() ?> 08 </head> 09 <body onload="test()"> 10 <div class="test">Hello Zend Framework – QHOnline.Info</div> 11 </body> 12 </html> Chạy thử nghiệm: http://localhost/zfexample/index/test Kết quả: Title, meta, Css và javascript sẽ có tác dụng
  • 15. Như bạn thấy đấy, ở trong đoạn code trên testAction() ta sử dụng phương thức: $baseurl=$this->_request->getbaseurl(); Đó là bởi vì, những gì mà chúng ta muốn tương tác được trong view như css, javascript, hình ảnh hiển thị thì buộc chúng ta phải lấy được đường dẫn hiển thị ứng dụng zend framework. Và với $baseurl ở trên thực chất là chúng ta sẽ lấy được thư mục hiện hành của ứng dụng là /zfexample. Và từ đó ta gọi tiếp các thông tin còn lại như css, js và hình ảnh hiển thị. -------------------------o0o----------------------------- Khi sử dụng layout, thì mọi dữ liệu của view đểu sẽ hiển thị trong vùng chỉ định của layout đó mà chúng ta không cần phải khai báo chúng trong từng view một. Như vậy, nói cách khác chúng ta sẽ không cần quan tâm đến bộ cục của layout khi làm việc với view. Mà chỉ quan tâm đến dữ liệu, vai trò mà view đó thể hiện như thế nào mà thôi. Để làm được điều đó, trong file application.ini ta thêm vào 2 dòng sau: 1 resources.layout.layout="layout" 2 resources.layout.layoutPath=APPLICATION_PATH "/layouts/scripts" Ý nghĩa của 2 dòng này như thế nào ?. + Dòng đầu tiên cho ta biết file chứa layout của chúng ta tên là layout + Dòng thứ hai cho ta biết đường dẫn tới file layout này như thế nào. Với 2 dòng ở trên ta hoàn toàn có thể cấu hình thay đổi tên và đường dẫn theo ý thích của riêng ta một cách dễ dàng. Kế tới, ta tạo thư mục layouts/scripts. Và tạo file layout.phtml trong thư mục này với nội dung như sau: 01 <?php echo $this->doctype() ?> 02 <html> 03 <head> 04 <?php echo $this->headTitle() ?> 05 <?php echo $this->headMeta() ?> 06 <?php echo $this->headLink() ?> 07 <?php echo $this->headScript() ?> 08 </head>
  • 16. 09 <body> 10 <?php 11 echo $this->layout()->content; 12 ?> 13 </body> 14 </html> Bạn thấy đấy, cấu trúc của nó giống với phần view ở bài tìm hiểu cơ bản về zend view phải không nào. Chỉ có sự khác biệt là phần nội dung body. Chúng ta dùng cú pháp: 1 $this->layout()->content; Cú pháp này sẽ gọi các view của controller vào để hiện thị trên bố cục này. Vậy trong IndexController.php ta viết đoạn lệnh như sau: 1 <?php 2 class IndexController extends Zend_Controller_Action{ 3 public function init(){ 4 $this->view->headTitle("QHOnline - Zend Layout") 5 } 6 public function indexAction(){ 7 echo "<h1>Welcome to Zend Framework - QHOnline.Info"; 8 } 9} Ở đoạn code phía trên, tôi sử dụng phương thức init(). Đây là phương thức mặc định sẽ được gọi đầu tiên khi chúng ta tiến hành chạy controller này. Và dĩ nhiên, khi bạn chạy bất kể một action nào thì init() cũng sẽ được gọi trước hết. Và trong ví dụ này, công việc của init() là hiển thị thông tin tiêu đề của trình duyệt là QHOnline- Zend Layout. Khi bạn chạy ứng dụng, sẽ thấy view của chúng ta được nằm trong một bố cục mà bạn đã bố trí một cách hợp lý. Ngoài cách cấu hình trực tiếp trong file application.ini ra, chúng ta cũng có thể cấu hình và gọi trực tiếp chúng bởi việc gọi nạp trong các controller như sau: 01 <?php 02 class IndexController extends Zend_Controller_Action{ 03 public function init(){ 04 $option=array( 05 "layout" => "layout", 06 "layoutPath" => APPLICATION_PATH."/layouts/scripts/" 07 ); 08 Zend_Layout::startMvc($option); 09 $this->view->headTitle("QHOnline - Zend Layout") 10 } 11 public function indexAction(){ 12 echo "<h1>Welcome to Zend Framework - QHOnline.Info"; 13 }
  • 17. 14 } Như bạn thấy đấy, ở trên tôi tạo ra một mảng chứa 2 tham số là layout để chứa tên file và đường dẫn của layout nhằm gọi tới thư mục chứa layout. Sau đó tôi gọi lớp Zend_Layout đồng thời gọi phương thức starMVC() để truyền tham số mà chúng ta vừa thiết lập trong mảng. Khi chạy ứng dụng thì kết quả hiển thị so với phương pháp cấu hình trong application là như nhau. Vậy sự khác biệt giữa hai phương pháp cấu hình này là gì ?. + Phương pháp cấu hình bằng application.ini cho phép ta chỉ thiết lập một lần, sau đó các controller không cần phải thiết lập lại. Nhưng chúng chỉ cố định duy nhất một layout cho tất cả ứng dụng. + Phương pháp cấu hình trực tiếp tuy phải cấu hình trong từng controller nhưng có thể cho ta tùy chọn thay đổi theo chiều hướng multi layout cho từng module hoặc controller mà ta muốn một cách dễ dàng. Sử dụng 2 phương pháp này thế nào và ra sao là còn tùy vào sự linh động và sáng tạo trong lập trình của các bạn. Kết thúc bài này, tôi đã hướng dẫn bạn sử dụng layout trong zend framework để tạo master page đồng thời hướng tới khái niệm multi layout cho ứng dụng với những tùy chọn mà bạn mong muốn. Trong bài tới, chúng ta sẽ cùng tìm hiểu về tương tác cơ sở dữ liệu trong zend framework ra sao, qua đó vận dụng model trong zend framework như thế nào. Vậy trước hết, ta tìm hiểu xem model là gì ?. Và tại sao phải sử dụng model ?. Model là tầng xử lý những tác vụ liên quan đến tương tác cơ sở dữ liệu từ những yêu cầu của controller. Model xử lý và trả về kết quả dưới dạng một mảng dữ liệu, khi đó thông qua view ta sẽ đẩy nội dung của mảng dữ liệu ấy ra bên ngoài. Việc tách biệt tầng model có rất nhiều thuận lợi, trước là dễ quản lý sau là dễ nâng cấp và phát triển trong tương lai của mã nguồn. Để tương tác được với Model thì trước tiên ta phải kết nối được với cơ sở dữ liệu. Vậy ta tạo 1 bảng user với các cú pháp như sau: 01 CREATE TABLE user ( 02 id int(10) unsigned NOT NULL AUTO_INCREMENT, 03 username varchar(50) NOT NULL, 04 password char(32) NOT NULL, 05 level int(1) NOT NULL DEFAULT '1', 06 PRIMARY KEY (id) 07 ); 08 INSERT INTO 'user' (username,password,level) VALUES('admin', '12345', 2); 09 INSERT INTO 'user' (username,password,level) VALUES('kenny', '12345', 2);
  • 18. 10 INSERT INTO 'user' (username,password,level) VALUES('jacky', '12345', 1); 11 INSERT INTO 'user' (username,password,level) VALUES('Lena', '12345', 1); Tiếp tục ta kết nối với cơ sở dữ liệu bằng cách thêm vào file application.ini của chúng ta những đoạn lệnh sau: 1 resources.db.adapter = "Pdo_mysql" 2 resources.db.params.host = "localhost" 3 resources.db.params.username = "root" 4 resources.db.params.password = "" 5 resources.db.params.dbname = "qhonline" Đoạn thông tin này khai báo cho hệ thống biết các tham số như host, user, pass, dbname. Sau khi đã kết nối được với cơ sở dữ liệu, tiếp theo. Chúng ta sẽ tạo file User.php trong thư mục Model với nội dung như sau: 1 <?php 2 class Model_User extends Zend_Db_Table_Abstract{ 3 protected $_name="user"; 4 protected $_primary="id"; 5 public function listall(){ 6 return $this->fetchall()->toArray(); 7 } 8} Qua đoạn lệnh trên ta hiểu phần nào về quy tắc định nghĩa một lớp model trong zend framework. Vì tất cả các file nằm trong thư mục Model nên áp dụng theo cơ chế lazy loading ta có quy tắc định nghĩa: Model_Tênfile. Cụ thể ở đây tôi tạo ra file User.php, nên lớp của tôi định nghĩa sẽ là Model_User. Lưu ý là thư mục Models của chúng ta có s, nhưng khi định nghĩa thì chúng ta bỏ qua s và viết bình thường là Model. Trong lớp Model_User ở trên, ta kế thừa lớp Zend_Db_Table_Abstract. Và khai báo tên bảng, tên khóa chính thông qua hai thuộc tính $_name và $_primary. Cuối cùng, ta định nghĩa phương thức listall() và dùng phương thức fetchall() để lấy toàn bộ dữ liệu vốn có trong bảng user. Ở đây zend framework sử dụng cơ chế Active Record. Nên phương thức $this->fetchall() nó tương đương với cú pháp lặp toàn bộ dữ liệu từ câu truy vấn select * from user vậy. Sau cùng, ta tạo lớp UserController trong file controllers/UserController.php với nội dung sau: 1 <?php 2 class UserController extends Zend_Controller_Action{ 3 public function indexAction(){ 4 $muser=new Model_User; 5 echo "<pre>"; 6 print_r($muser->listall()); 7 echo "</pre>";
  • 19. 8 } 9} Lưu ý là ta phải tạo trong thư mục views/scripts/user/index.phtml để controller tìm kiếm thấy view khi được gọi. (xem bài tìm hiểu về view trong zend framework). Để sử dụng được Model trong controller ta phải khởi tạo đối tượng từ lớp Model mà ta đã định nghĩa ở trên. Sau đó từ đối tượng ta lại gọi các phương thức muốn thực thi. Lệnh <pre> ở trên được dùng để trình bày dữ liệu dạng mảng. Chạy thử nghiệm với đường dẫn: http://localhost/zfexam/user/ Kết quả sẽ thông báo lỗi: Fatal error: Class 'Model_User' not found in C:xampphtdocszfexamapplicationcontrollersUserController.php on line 4 Hệ thống của chúng ta chưa hiểu được lớp Model_User. Vì thế ta cần phải định nghĩa như sau trong file bootstrap.php: 01 <?php 02 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{ 03 protected function _initAutoload(){ 04 $autoloader = new Zend_Application_Module_Autoloader(array( 05 'namespace' => '', 06 'basePath' => dirname(__FILE__), 07 )); 08 return $autoloader; 09 } 10 } Như các bạn thấy đấy, ta đã thêm vào phương thức autoload để định nghĩa cho hệ thống biết được đường dẫn tới các lớp mà ta tạo trong Model và form sau này. Chạy thử nghiệm lại với đường dẫn: http://localhost/zfexam/user/ Kết quả sẽ hiển thị danh sách user dưới dạng mảng như ta mong đợi. Một số phương thức thường dùng trong lớp Zend_Db_Table 1- Thao tác liệt kê và nhận dữ liệu: Để có thể thực hiện các thao tác liệt kê dữ liệu đầy đủ và chi tiết. Chúng ta cần sử dụng phương thức: 1 $this->select(); Và từ phương thức này, chúng ta sẽ gọi các thao tác khác liên quan như điều kiện, giới hạn, sắp xếp,… 1 $query=$this->select(); + Liệt kê dữ liệu theo cột:
  • 20. 1 $query->from('tên_bảng',array('cột 1','cột 2')); + Liệt kê dữ liệu với một điều kiện: 1 $query->where('cột =?','giá trị'); Cú pháp ở trên cho ta liệt kê dữ liệu với điều kiện cột bằng giá trị nào đó. Quy tắc trong zend framework đối với mệnh đề where là tên cột, rồi đến phép so sánh, rồi đến ký hiệu "?". Và sau cùng là mới là giá trị. + Sắp xếp dữ liệu theo cột thuộc tính 1 $query->order('tên_cột ASC hoặc DESC'); +Giới hạn dữ liệu hiển thị 1 $query->limit(vị trí bắt đầu, số record muốn hiển thị); + Hiển thị tất cả thông tin: 1 $this->fetchall(); Trường hợp hiển thị với các điều kiện ở phía trên thì ta truyền $query vào fetchall() 1 $this->fetchall($query); + Hiển thị 1 dòng dữ liệu 1 $this->fetchRow(); Ví dụ đầy đủ về hiển thị dữ liệu: 1 public function listuser(){ 2 $data=$this->select(); 3 $data->from('user',array('username','id')); 4 $data->where('id > ?',1); 5 $data->order('username DESC'); 6 $data->limit(3); 7 $data=$this->fetchAll($data); 8 return $data; 9} 2- Thao tác thêm, xóa, sửa dữ liệu: + Thêm dữ liệu: 1 $this->insert($data); Ví dụ: 1 public function insert_user($data){ 2 3 $this->insert($data); 4} + Sửa dữ liệu: 1 $this->update($data,$where); Ví dụ: 1 public function update_user($data,$where){ 2 $where="id='1'"; 3 $this->update($data,$where); 4}
  • 21. Với $data của chúng ta là một mảng dữ liệu: 1 $data=array( 2 "username" => "kenny", 3 "password" => "12345", 4 "level" => "2" 5 ); + Xóa dữ liệu: 1 $this->delete($where); Ví dụ: 1 public function delinfo($id){ 2 $where="id=".$id; 3 $this->delete($where); 4} Kết thúc bài này, ta đã hiểu được cơ bản về cách thức sử dụng Model trong Zend Framework, đồng thời cũng nắm được phần nào về các phương thức phổ biến thường sử dụng trong ứng dụng. Trong bài kế tiếp, tôi sẽ hướng dẫn các bạn tìm hiểu về phương pháp tương tác với cơ sở dữ liệu trên lớp Zend_Db. Qua đó có sự tùy biến tốt hơn trong việc viết ứng dụng trên zend framework Trước hết, ta cần tìm hiểu về lớp Zend_Registry. Đây là thư viện tạo ra một giá trị toàn cục trong ứng dụng của chúng ta, nó có thể chứa giá trị, mảng và một đối tượng. Để thiết lập ta sử dụng cú pháp: 1 Zend_Registry::set('tên','giá trị'); Sau khi tiết thiết lập, ta có thể lấy giá trị ở bất kỳ đâu bởi cú pháp: 1 Zend_Registry::get('tên'); Trong bài này, ta sử dụng chúng để lưu trữ hành động kết nối với cơ sở dữ liệu của chúng ta. Tạo cơ sở dữ liệu và thêm dữ liệu vào bảng theo cú pháp sau: 01 CREATE TABLE user ( 02 id int(10) unsigned NOT NULL AUTO_INCREMENT, 03 username varchar(50) NOT NULL, 04 password char(32) NOT NULL, 05 level int(1) NOT NULL DEFAULT '1', 06 PRIMARY KEY (id) 07 ); 08 INSERT INTO 'user' (username,password,level) VALUES('admin', '12345', 2); 09 INSERT INTO 'user' (username,password,level) VALUES('kenny', '12345', 2); 10 INSERT INTO 'user' (username,password,level) VALUES('jacky', '12345', 1); 11 INSERT INTO 'user' (username,password,level) VALUES('Lena', '12345', 1);
  • 22. Khai báo kết nối cơ sở dữ liệu tại file application/configs/application.ini như sau: 1 resources.db.adapter = "Pdo_mysql" 2 resources.db.params.host = "localhost" 3 resources.db.params.username = "root" 4 resources.db.params.password = "" 5 resources.db.params.dbname = "qhonline" Tiếp tục, mở file bootstrap.php thêm đoạn code sau: 1 <?php 2 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{ 3 protected function _initDatabase(){ 4 $db = $this->getPluginResource('db')->getDbAdapter(); 5 Zend_Registry::set('db', $db); 6 } 7} Theo đoạn code trên, ta thêm vào phương thức initDatabase(). Đây là phương thức sẽ được triệu gọi khi chạy ứng dụng. Tại đây, ta lấy thông tin kết nối từ nội dung đã cấu hình ở file application.ini. Kế tới, ta thực hiện việc tạo registry để lưu trữ đối tượng kết nối này. Tại thư mục Models, ta tạo file tên User.php Với nội dung lớp này như sau: 01 <?php 02 class Model_User{ 03 protected $db; 04 public function __construct(){ 05 $this->db=Zend_Registry::get('db'); 06 } 07 public function listall(){ 08 $sql=$this->db->query("select * from user order by id DESC"); 09 return $sql->fetchAll(); 10 } 11 } Như bạn thấy, tại lớp Model_User này trước hết ta tạo một construct() lấy giá trị từ registry để đưa vào thuộc tính tên $db. Để mỗi khi ta khởi tạo đối tượng thì đối tượng kết nối đã được tạo sẵn. Kế đến ta tạo phương thức listall() thực hiện công việc liệt kê toàn bộ người dùng có trong bảng user. Lúc này, để thực hiện được câu truy vấn thì ta dùng phương thức query() chạy. Và lấy kết quả bới phương thức fetchAll() . Tiếp tục, tại controller User ta gọi model như sau: 01 <?php 02 class UserController extends Zend_Controller_Action{ 03 public function indexAction(){
  • 23. 04 $muser=new Model_User; 05 $data=$muser->listall(); 06 echo "<pre>"; 07 print_r($data); 08 echo "</pre>"; 09 } 10 } Đoạn code trên có tác dụng gọi model user và gọi tiếp phương thức listall() của model để hiện thị thông tin của người dùng bởi các thẻ thử nghiệm bên dưới. Với phương pháp tương tác này, rõ ràng chúng ta có thể chạy bất cứ câu lệnh nào mà ta muốn trong ứng dụng một cách dễ dàng. Đồng thời, có thể tạo ra những tùy biến kết hợp giữa Zend_Db_Table và Zend_Db. Chẳng hạn, với câu truy vấn đơn giản, ta có thể sử dụng Zend_Db_Table để lấy giá trị. Nhưng với các câu truy vấn phức tạp đòi hỏi phải kết bảng, xử lý nhiều, thì việc dùng cách tương tác Zend_Db lại là sử lựa chọn hiệu quả nhất. 01 <?php 02 class Model_User extends Zend_Db_Table_Abstract{ 03 protected $_name="user"; 04 protected $_primary="id"; 05 protected $db; 06 public function __construct(){ 07 $this->db=Zend_Registry::get('db'); 08 } 09 public function listall(){ $sql=$this->db->query("select * from user where level='1' order by 10 id DESC"); 11 return $sql->fetchAll(); 12 } 13 public function listall2(){ 14 $query=$this->select(); 15 $query->where('level =?','2'); 16 return $thisp>fetchAll($query); 17 } 18 } Ở trên là một ví dụ về sự kết hợp cả hai, với listall() là phương thức sử dụng câu truy vấn thuần. Trong khi listall2() ta sử dụng mô hình active record để lấy dữ liệu. Kết thúc bài này, ít nhiều chúng ta đã có thể định hình và hiểu rõ hơn về cơ chế tương tác cơ sở dữ liệu trong zend framework. Qua đó có thể vận dụng linh hoạt chúng trong thực tế để giải quyết các vấn đề về cơ sở dữ liệu. Trong bài tiếp theo tôi sẽ hướng dẫn các bạn tìm hiểu và sử dụng lớp Zend_Paginator để phân trang dữ liệu cho ứng dụng.
  • 24. Phân trang là kỹ thuật có lẽ đã không còn xa lạ gì với những ai đã và đang viết web. Việc phân trang sẽ giúp cho ứng dụng của bạn thao tác nhanh hơn và gọn hơn mỗi khi đổ dữ liệu ra bên ngoài, vì thế có thể xem nó là một lớp quan trọng trong mọi ứng dụng hiện nay. Trước hết ta thực hiện việc khởi tạo và khai báo thông tin kết nối cơ sở dữ liệu. 01 CREATE TABLE user ( 02 id int(10) unsigned NOT NULL AUTO_INCREMENT, 03 username varchar(50) NOT NULL, 04 password char(32) NOT NULL, 05 level int(1) NOT NULL DEFAULT '1', 06 PRIMARY KEY (id) 07 ); 08 INSERT INTO user(username,password,level) VALUES ('admin', '12345', '2'); 09 INSERT INTO user(username,password,level) VALUES ('kenny', '12345', '2'); 10 INSERT INTO user(username,password,level) VALUES ('jacky', '12345', '1'); 11 INSERT INTO user(username,password,level) VALUES ('vivi', '12345', '1'); 12 INSERT INTO user(username,password,level) VALUES ('abc', '123', '1'); 13 INSERT INTO user(username,password,level) VALUES ('mimi123', '12345', '1'); 14 INSERT INTO user(username,password,level) VALUES ('mimi456', '12345', '1'); 15 INSERT INTO user(username,password,level) VALUES ('mimi789', '123', '1'); Kế đến ta khai báo kết nối trong file application.ini 1 resources.db.adapter = "Pdo_mysql" 2 resources.db.params.host = "localhost" 3 resources.db.params.username = "root" 4 resources.db.params.password = "" 5 resources.db.params.dbname = "qhonline" Tại thư mục models ta tạo file user.php với nội dung bên dưới để thực hiện việc hiển thị thông tin ra bên ngoài. (Xem lại bài tương tác với cơ sở dữ liệu với Zend_Db_Table) 1 <?php 2 class Model_User extends Zend_Db_Table_Abstract{ 3 protected $_name="user"; 4 protected $_primary="id"; 5 public function listall(){ 6 return $this->fetchAll()->toArray(); 7 } 8} Tiếp tục tại thư mục controllers ta tạo file tên UserController.php với nội dung: 01 <?php 02 class UserController extends Zend_Controller_Action{ 03 public function indexAction() 04 {
  • 25. 05 $muser=new Model_User; 06 $paginator = Zend_Paginator::factory($muser->listall()); 07 $paginator->setItemCountPerPage(3); 08 $paginator->setPageRange(3); 09 $currentPage = $this->_request->getParam('page',1); 10 $paginator->setCurrentPageNumber($currentPage); 11 $this->view->data=$paginator; 12 } 13 } Tại controller này ta thực hiện việc cấu hình phân trang như sau: + Trước tiên ta nạp model user vào để gọi phương thức listall(). + Tiếp tục ta khởi tạo lớp Zend_Paginatior và truyền tham số lấy được từ model qua. Tham số này là một cái mảng liệt kê toàn bộ thành viên có trong bảng. + Kế tới ta cấu hình số lượng dữ liệu hiển thị trên trang. Cụ thể trong bài ta đang quy ước là 3 dòng dữ liệu trên 1 trang. + Ta cấu hình hiển thị 1 lần chỉ 3 trang. + Lấy trang hiện hành và mặc định sẽ là trang một. + Đưa tham số trang hiện hành vào phương thức setCurrentPageNumber() + Cuối cùng, ta đổ dữ liệu ra view. Tiếp tục ta tạo view index.phtml tại thư mục: views/script/user/ 01 <tr> 02 <td>User Id</td> 03 <td>Username</td> 04 <td>Level</td> 05 </tr> 06 <?php 07 foreach($this->data as $item) 08 { 09 echo "<tr>"; 10 echo "<td align='center'>".$item['id']."</td>"; 11 echo "<td align='center'>".$item['username']."</td>"; 12 if($item['level'] == 1){ 13 echo "<td align='center'>Member</td>"; 14 }else{ 15 echo "<td align='center'><font color='red'>Admin</font></td>"; 16 } 17 echo "</tr>"; 18 } 19 ?> 20 </table> 21 <?php echo $this->paginationControl($this->data, 'Sliding' , 22 'user/pagination.phtml');
  • 26. 23 ?> Công việc của file view này là nhận dữ liệu từ controller và thực hiện việc lặp đỗ dữ liệu ra bên ngoài bằng lệnh foreach(). Ở phần cuối ta có thêm đoạn lệnh sau: 1 <?php echo $this->paginationControl($this->data, 'Sliding' , 2 'user/pagination.phtml'); 3 ?> Đây là phần ta nạp 1 file phtml với mục đích hiển thị các liên kết tới, lùi, số trang của ứng dụng. Tại views/scripts/user tạo file pagination.phtml như cấu hình ở trên với nội dung: 01 <?php if ($this->pageCount): ?> 02 <div class="paginationControl" align="center"> 03 <?php 04 if (isset($this->previous)){ echo '<a href="' . $this->url(array('page' => $this->previous)). 05 '"> < Previous</a> | '; 06 } 07 foreach ($this->pagesInRange as $page){ 08 if ($page != $this->current){ 09 echo '<a href="' . $this->url(array('page' => $page)). '">' . $page . '</a> | '; 10 }else{ 11 echo $page . ' | '; 12 } 13 } 14 if (isset($this->next)){ echo '<a href="' . $this->url(array('page' => $this->next)) . 15 '">Next ></a>'; 16 } 17 ?> 18 </div> 19 <?php endif; ?> Sau khi hoàn tất, chạy ứng dụng ta sẽ thấy kết quả hiển thị như bên dưới. Về mặt cơ bản thì Zend_Paginator làm công việc đưa tất cả record của câu truy vấn vào trong 1 mảng dữ liệu. Sau đó nó phân trang trực tiếp từ dữ liệu trong mảng này. Điều này trên thực tế thì chỉ có thể đáp ứng được với mô hình dữ liệu nhỏ, vì nếu dùng với hàng trăm ngàn dòng dữ liệu thì có lẽ việc đem chúng đổ vào mảng thôi cũng là điều không đơn giản. Nhóm phát triển Zend Framework cũng hiểu những khó khăn từ phía người sử dụng về điều này, nên các phiên bản sau này của zend đã hỗ trợ thêm nhiều phương thức nhằm giải quyết bài toán này.
  • 27. Đó là sử dụng thêm phương thức bên dưới với các tham số truyền vào, trước khi gọi lớp Zend_Paginator. 1 new Zend_Paginator_Adapter_DbSelect() Để thực hiện nó, trước hết ta thay đổi phương thức listall() trong model User như sau: 01 <?php 02 class Model_User extends Zend_Db_Table_Abstract{ 03 protected $_name="user"; 04 protected $_primary="id"; 05 public function listall(){ 06 $query=$this->select(); 07 $query->from($this->_name,array('id','username','level')); 08 return $query; 09 } 10 } Như bạn thấy, phương thức listall() của chúng ta giờ đây không còn là fetchall() nữa rồi. Mà công việc của nó chỉ là thực hiện việc chọn bảng, chọn số lượng cột để hiển thị. Kế tới tại UserController.php ta sửa lại như sau: 01 <?php 02 class UserController extends Zend_Controller_Action{ 03 public function indexAction(){ 04 $muser=new Model_User; 05 $adapter = new Zend_Paginator_Adapter_DbSelect($muser->listall()); 06 $paginator = new Zend_Paginator($adapter); 07 $paginator->setItemCountPerPage(3); 08 $paginator->setPageRange(3); 09 $currentPage = $this->_request->getParam('page',1); 10 $paginator->setCurrentPageNumber($currentPage); 11 $this->view->data=$paginator; 12 } 13 } Ta truyền phương thức listall() vào lớp Zend_Paginator_Adapter_DbSelect. Tại đó, tự nó sẽ biết phải lấy dữ liệu như thế nào. Cuối cùng, thay vì ta dù ng Zend_Paginator::factory() thì nay ta khởi tạo hẳn một phương thức và truyền dữ liệu mà ta đã cấu hình ở trên vào. Chạy ứng dụng, bạn sẽ thấy kết quả giống với lúc ta dùng ở trên. Vậy liệu chúng có khác gì không ?. Vì dẫu sao cả hai cùng làm công việc hiển thị toàn bộ dữ liệu cơ mà ?. Giờ bạn hãy mở file index.phtml ra và thêm vào dòng lệnh sau để xem kiến trúc bên trong mảng của data trước khi đổ ra có gì nhé. 1 <?php 2 echo "<pre>";
  • 28. 3 print_r($this->data); 4 echo "</pre>"; 5 ?> Và kết quả thật sự bất ngờ phải không nào, trong mảng dữ liệu của chúng ta hoàn toàn không có dòng nào liên quan đến dữ liệu có trong bảng cả. Vậy Zend_Paginator tự hiểu và tự giới hạn dữ liệu trả về giúp cho chúng ta. Ngay trên manual của Zend Framework cũng nhấn mạnh về điều này khi bạn sử dụng thêm lớp Zend_Paginator_Adapter_DbSelect(). Additionally these adapters do not fetch all records from the database in order to count them. Instead, the adapters manipulates the original query to produce the corresponding COUNT query. Paginator then executes that COUNT query to get the number of rows.This does require an extra round-trip to the database, but this is many times faster than fetching an entire result set and using count(). Especially with large collections of data. Phần bôi đen màu đỏ là phần tôi muốn các bạn chú ý khi tham khảo đoạn thông tin trên từ manual của Zend Framework. Tải toàn bộ mã nguồn của bài học tại đây Như vậy, qua phần này. Tôi đã hướng dẫn các bạn bước đầu làm quen và tìm hiểu được lớp Zend_Paginator, từ đó sử dụng chúng cho công việc phân trang dữ liệu trong ứng dụng. Tiếp tục ở bài sau, chúng ta sẽ cùng tìm hiểu về lớp Zend_Form, đồng thời dùng nó để xây dựng các biểu mẫu nhập liệu như thế nào.