[ZF2] Thao tác với Database – Phần 3
|Trong bài viết [ZF2] Cấu hình Routing và Controllers – Phần 2, chúng ta đã cấu hình routing và controllers cho module Album với 4 action chính giúp hiển thị, thêm, xóa, sửa toàn bộ sưu tập nhạc thông qua các view script tương ứng. Trong mô hình MVC của Zend Framework 2 thì chúng ta đã tìm hiểu và cài đặt 2 thành phần chính là Controller – View, và trong bài viết này chúng ta sẽ cài đặt cấu hình tiếp thành phần Model cho module Album để có thể tương tác với cơ sở dữ liệu thông qua các câu lệnh truy vấn. Chúng ta sẽ sử dụng lớp Zend\Db\TableGateway\TableGateway để tìm kiếm, insert, update, delete với cơ sở dữ liệu lưu trữ bộ sưu tập nhạc.
Chúng ta sẽ sử dụng hệ quản trị cơ sở dữ liệu Mysql và dùng lớp kết nối dữ liệu PDO – PHP để tạo một database có tên zf2tutorial và chạy câu lệnh sql giúp tạo một bảng album với một số trường mẫu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
CREATE TABLE album ( id int(11) NOT NULL auto_increment, artist varchar(100) NOT NULL, title varchar(100) NOT NULL, PRIMARY KEY (id) ); INSERT INTO album (artist, title) VALUES ('The Military Wives', 'In My Dreams'); INSERT INTO album (artist, title) VALUES ('Adele', '21'); INSERT INTO album (artist, title) VALUES ('Bruce Springsteen', 'Wrecking Ball (Deluxe)'); INSERT INTO album (artist, title) VALUES ('Lana Del Rey', 'Born To Die'); INSERT INTO album (artist, title) VALUES ('Gotye', 'Making Mirrors'); |
Bây giờ, chúng ta đã có một bảng album trong database zf2tutorial và một số trường dữ liệu mẫu trong bảng album.
Xây dựng lớp Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
namespace Album\Model; class Album { public $id; public $artist; public $title; public function exchangeArray($data) { $this->id = (!empty($data['id'])) ? $data['id'] : null; $this->artist = (!empty($data['artist'])) ? $data['artist'] : null; $this->title = (!empty($data['title'])) ? $data['title'] : null; } } |
Tiếp theo, chúng ta sẽ tạo lớp AlbumTable trong tập tin AlbumTable.php được đặt trong thư mục module/Album/src/Album/Model, lớp này sẽ xây dựng các phương thức xử lý nghiệp vụ tương tác với cơ sở dữ liệu như lấy toàn bộ bộ sưu tập, thêm mới một bộ sưu tập…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
namespace Album\Model; use Zend\Db\TableGateway\TableGateway; class AlbumTable { protected $tableGateway; public function __construct(TableGateway $tableGateway) { $this->tableGateway = $tableGateway; } public function fetchAll() { $resultSet = $this->tableGateway->select(); return $resultSet; } public function getAlbum($id) { $id = (int) $id; $rowset = $this->tableGateway->select(array('id' => $id)); $row = $rowset->current(); if (!$row) { throw new \Exception("Could not find row $id"); } return $row; } public function saveAlbum(Album $album) { $data = array( 'artist' => $album->artist, 'title' => $album->title, ); $id = (int) $album->id; if ($id == 0) { $this->tableGateway->insert($data); } else { if ($this->getAlbum($id)) { $this->tableGateway->update($data, array('id' => $id)); } else { throw new \Exception('Album id does not exist'); } } } public function deleteAlbum($id) { $this->tableGateway->delete(array('id' => (int) $id)); } } |
Lớp AlbumTable khi khởi tạo sẽ nhận một tham số là một thể hiện của lớp Zend\Db\TableGateway\TableGateway và gán vào biến thuộc tính lớp $tableGateway, thuộc tính này sẽ được sử dụng trong các phương thức xử lý nghiệp vụ của lớp AlbumTable với cơ sở dữ liệu thông qua các phương thức select(), insert(), delete()… Các phương thức chính trong lớp AlbumTable là:
- fecthAll() : giúp lấy ra toàn bộ dữ liệu về các bộ sưu tập có trong cơ sở dữ liệu
- getAlbum($id): giúp lấy một bộ sưu tập chỉ định thông qua tham số đầu vào $id – số nguyên
- saveAlbum(Album $album): giúp lưu thông tin của một album vào cơ sở dữ liệu, có thể là chỉnh sửa hoặc thêm mới
- deleteAlbum($id): xóa bỏ một bộ sưu tâp nhạc thông qua một biến $id chỉ định
Bước tiếp theo chúng ta sẽ khai báo một factories Album\Model\AlbumTable với ServiceManager để có thể dễ dàng quản lý và khởi tạo một đối tương Album\Model\AlbumTable. Trong tập tin module/Album/Module.php chúng ta sẽ thêm phương thức getServiceConfig() vào lớp Album\Module, phương thức này sẽ trả ra một mảng và nó sẽ được nạp vào ServiceManager khi module Album được load. Các factories như Album\Model\AlbumTable và AlbumTableGateway sẽ được khởi tạo thông qua ServiceManager.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
namespace Album; // Add these import statements: use Album\Model\Album; use Album\Model\AlbumTable; use Zend\Db\ResultSet\ResultSet; use Zend\Db\TableGateway\TableGateway; class Module { // getAutoloaderConfig() and getConfig() methods here // Add this method: public function getServiceConfig() { return array( 'factories' => array( 'Album\Model\AlbumTable' => function($sm) { $tableGateway = $sm->get('AlbumTableGateway'); $table = new AlbumTable($tableGateway); return $table; }, 'AlbumTableGateway' => function ($sm) { $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter'); $resultSetPrototype = new ResultSet(); $resultSetPrototype->setArrayObjectPrototype(new Album()); return new TableGateway('album', $dbAdapter, null, $resultSetPrototype); }, ), ); } } |
Chúng ta cần phải thiết lập một driver kết nối cơ sở dữ liệu bằng cách tạo một tập tin cấu hình db.global.php trong thư mục config/autoload với nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
return array( 'db' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=zf2tutorial;host=localhost', 'driver_options' => array( PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'' ), ), 'service_manager' => array( 'factories' => array( 'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory', ), ), ); |
Nhưng thông tin kết nối tới database như username và password đăng nhập sẽ được khai báo trong tập tin db.local.php đặt trong thư mục config/autoload như sau:
1 2 3 4 5 6 |
return array( 'db' => array( 'username' => 'YOUR USERNAME HERE', 'password' => 'YOUR PASSWORD HERE', ), ); |
Lớp Zend\Db\Adapter\AdapterServiceFactory sẽ được ServiceManger sử dụng để khởi tạo đối tượng kết nối database thông qua tham số cấu hình ‘db’ . Factories này được ánh xạ với tên Zend\Db\Adapter\Apdater và ServiceManager có thể tạo một đối tượng mới thông qua tên này.
Lưu ý: Những tập tin autoload *.global.php sẽ được đồng bộ lên Github và *.local.php sẽ được bỏ qua. Để đảm bảo tính bảo mật các bạn nên để các thông tin như username và passwork trong tập tin *.local.php
Xử lý dữ liệu trong Contrller
Lớp Album\Controller\AlbumController sẽ chịu trách nhiệm tương tác với Model, và chúng ta sử dụng các phương thức đã xây dựng ở lớp Album\Model\AlbumTable để thực hiện xử lý một cách dễ dàng. Chúng ta sẽ thêm phương thức getAlbumTable() để có thể lấy ra được đối tượng của lớp Album\Model\AlbumTable.
1 2 3 4 5 6 7 8 9 |
// module/Album/src/Album/Controller/AlbumController.php: public function getAlbumTable() { if (!$this->albumTable) { $sm = $this->getServiceLocator(); $this->albumTable = $sm->get('Album\Model\AlbumTable'); } return $this->albumTable; } |
$sm->get(‘Album\Model\AlbumTable’); sẽ trả ra một đối tượng của lớp Album\Model\AlbumTable và nó sẽ được gán vào thuộc tính $albumTable của lớp AlbumController.
1 |
protected $albumTable; |
Hiển thị toàn bộ bộ sưu tập
Chúng ta sẽ sử dụng action ‘index‘ trong lớp AlbumController để lấy toàn bộ bộ sưu tập có trong cơ sở dữ liệu, và đẩy các dữ liệu đó ra thành phần view thông qua việc trả ra một đối tượng lớp Zend\View\ViewModel.
1 2 3 4 5 6 7 8 9 |
// module/Album/src/Album/Controller/AlbumController.php: // ... public function indexAction() { return new ViewModel(array( 'albums' => $this->getAlbumTable()->fetchAll(), )); } // ... |
Nhận toàn bộ dữ liệu thông qua biến $this->albums, chúng ta sẽ sử dụng một vòng lặp để duyệt qua các trường dữ liệu và hiển thị chúng ra màn hình với các thẻ html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php // module/Album/view/album/album/index.phtml: $title = 'My albums'; $this->headTitle($title); ?> <h1><?php echo $this->escapeHtml($title); ?></h1> <p> <a href="<?php echo $this->url('album', array('action'=>'add'));?>">Add new album</a> </p> <table class="table"> <tr> <th>Title</th> <th>Artist</th> <th> </th> </tr> <?php foreach ($albums as $album) : ?> <tr> <td><?php echo $this->escapeHtml($album->title);?></td> <td><?php echo $this->escapeHtml($album->artist);?></td> <td> <a href="<?php echo $this->url('album', array('action'=>'edit', 'id' => $album->id));?>">Edit</a> <a href="<?php echo $this->url('album', array('action'=>'delete', 'id' => $album->id));?>">Delete</a> </td> </tr> <?php endforeach; ?> </table> |
Các phương thức headTitle(), escapeHtml(), url() trong tập tin hiển thị module/Album/view/album/album/index.phtml là các view helper hỗ trợ được ZF2 xây dựng sẵn và nạp khi dự án khởi chạy.
Và thành quả chúng ta nhận được khi truy nhập đường dẫn : http://zf2-tutorial.localhost/album

Kết nối database trong zf2