Adapter - Kết nối CSDL

Thư viện zend-db trong ZF3 dùng để kết nối và thi hành các lệnh SQL trên CSDL quan hệ. Bạn cần đảm bảo đã cài đặt bằng lệnh Composer sau:

composer require zendframework/zend-db

Trong ứng dụng Skeleton bạn cũng cần đảm bảo khai báo thêm 'Zend\Db' trong file config/modules.config.php để ứng dụng load Module này

Để làm việc với CSDL bạn cần tạo ra một đối tượng Zend\Db\Adapter\Adapter với cú pháp như sau:

use Zend\Db\Adapter\Adapter;

$configArray = [
    'driver'   => 'Mysqli',
    'database' => 'sitedata',
    'username' => 'admin',
    //...
    ];

$adapter = new Adapter($configArray);

$configArray là mảng cấu hình thông số với các key/giá trị có thể có như sau:

Key Phải có? Giá trị
driver Cần có Mysqli, Sqlsrv, Pdo_Sqlite, Pdo_Mysql, Pdo
database Thường có Tên database (schema)
username thường có username để kết nối
password thường có mật khẩu kết nối
hostname thường không cần IP hoặc hostname để kết nối
port thường không cần Cổng kết nối
charset thường không cần character set

Có một file CSDL MySQL mẫu xtdb bạn tải về và import vào MySQL Sever thực hành.

Dưới đây là cấu hình sử dụng một số driver kết nối phổ biến

Driver - Mysqli

Sử dụng đối tượng thư viện Mysqli để kết nối CSDL MySQL

$configArray = [
    'driver'   => 'Mysqli',
    'username' => 'root',
    'password' => '',
    'database' => 'xtdb',
    //'charset'  => 'utf8', //latin1
    ];

Driver - Pdo_Sqlite

Sử dụng kết nối tới CSDL SQLite

$configArray = [
    'driver'   => 'Pdo_Sqlite',
    'database' => 'path/to/sqlite.db',
    ];

Driver - Pdo_Mysql

Sử dụng đối tượng thư viện Pdo_Mysql để kết nối CSDL MySQL

$configArray = [
    'driver'   => 'Pdo_Mysql',
    'username' => 'root',
    'password' => '',
    'database' => 'xtdb',
    //'charset'  => 'utf8', //latin1
    ];

Driver - Pdo

Sử dụng Pdo cho phép dùng thư viện PDO để kết nối đến các loại CSDL khác nhau như MySQL, SQL Server

Ví dụ kết nối đến MySQL

$configArray = [
    'driver'   => 'Pdo',
    'username' => 'root',
    'password' => '',
    'dsn'            => 'mysql:dbname=xtdb;host=localhost',
    'driver_options' => [
        //PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'",
        ],
    ];

Thực hiện lệnh SQL

Có nhiều cách để thi hành và có được kết quả thi hành câu lệnh SQL

Thi hành ngay lập tức câu lệnh SQL

Gọi phương thức query với tham số thứ hai là hằng QUERY_MODE_EXECUTE thì sẽ thi hành ngay lệnh SQL và kết quả trả về là đối tượng Zend\Db\ResultSet\ResultSet chứa tập hợp kết quả truy vấn trả về

//$dbadapter là đối tượng Zend\Db\Adapter\Adapter

$query = "select * from Categories";

//Lấy ResultSet
$items = $dbadapter->query($query, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);

//Đọc dữ liệu query trả về
foreach ($items as $item) {
    var_dump($item);
}

Ví dụ bạn hãy import CSDL mẫu CSDL MySQL mẫu xtdb, sau đó tạo một ứng dụng Skeleton có tên là zend-db theo hướng dẫn như phần Cài đặt Skeleton Zend (composer: composer create-project -s dev zendframework/skeleton-application C:/wamp64/www/zend-db) để thực hành về Zend\Db

Bạn cũng có thể theo hướng dẫn di chuyển index.php ra thư mục gốc, chạy theo đường dẫn: http://localhost/zend-db/

Sau đó bạn thay nội dung hai file : module/Application/view/layout/layout.phtmlmodule/Application/view/application/index/index.phtml bằng layout.phtmlindex.phtml mục đích là sử dụng getBootstrap 4.x. Đồng thời nhớ chính 'config_cache_enabled', 'module_map_cache_enabled' là false trong file: config/application.config.php

Tạo action listcategory

module/Application/src/Controller/IndexController.php

//...
public function listcategoryAction() {
    $configArray   = [
        'driver'   => 'Mysqli',
        'username' => 'root',
        'password' => '',
        'database' => 'xtdb',
    ];

    $dbadapter = new \Zend\Db\Adapter\Adapter($configArray);
    $query = "select * from Categories";


    $results = $dbadapter->query($query,
        \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
    $categories = [];
    foreach ($results as $item) {
        $categories[] = $item;
    }

    return new ViewModel(['categories' => $categories]);
}
//...

Tạo template listcategory

<h1>Danhh sách các category</h1>
<?
$categories = $this->categories;
?>

<table class="table table-bordered">
    <tr>
        <th>CategoryID</th>
        <th>CategoryName</th>
        <th>Description</th>
    </tr>
    <?foreach ($categories as $cate):?>
        <tr>
            <td><?=$cate['CategoryID']?></td>
            <td><?=$cate['CategoryName']?></td>
            <td><?=$cate['Description']?></td>
        </tr>
    <?endforeach;?>
</table>    

Chạy thử với url: http://localhost/zend-db/application/listcategory

zenddb

Query Preparation

Khi gọi phương thức query với tham số thứ hai mặc định là QUERY_MODE_PREPARE thì nó trả về một đối tượng Statement (Zend\Db\Adapter\Driver\StatementInterface). Quy trình để thi hành một lệnh SQL như sau:

  • Tạo đối tượng Statement, ví dụ lệnh $adapter->query()
  • Inject đối tượng ParameterContainer chứa các tham số sẽ điền vào placeholder của câu lệnh vào Statement
  • Thi hành lệnh với phương thức $statement->execute()
  • Kiểm tra kết quả trả về và xử lý theo tình huống

Ví dụ sửa lại đoạn mã của action trên

module/Application/src/Controller/IndexController.php

//...
public function listcategoryAction() {

    $configArray   = [
        'driver'   => 'Mysqli',
        'username' => 'root',
        'password' => '',
        'database' => 'xtdb',
    ];

    $dbadapter = new \Zend\Db\Adapter\Adapter($configArray);
    $query = "select * from Categories where CategoryID	= ? or CategoryID = ?";
    $statement = $dbadapter->query($query);
    $statement->setParameterContainer(new ParameterContainer(
        [1,7]
    ));

    $results = $statement->execute();

    $categories = [];
    foreach ($results as $item) {
        $categories[] = $item;
    }
    return new ViewModel(['categories' => $categories]);
}
//...

Việc sử dụng phương thức query như trên để tạo ra Statement khuyến khích áp dụng với các query thực hiện một lần, chạy ngay. Trường hợp khác tốt hơn tạo ra Statement bằng cách:

$statement = $adapter->createStatement($sql, $optionalParameters);
$result    = $statement->execute();

Cấu hình tham số khởi tạo Adapter DB trong Skeleton

Để sử dụng đối tượng Zend\Db\Adapter\Adapter như một dịch vụ trong hệ thống quản lý bởi Service Manager (Chỉ một đối tượng Adapter trong hệ thống) thì bạn chỉ cần thiết lập tham số config ở cấp độ ứng dụng hoặc module.

Thường thì cấu hình Adapter kết nối DB khai bảo ở cấp độ ứng dụng, cụ thể trong file config: config/autoload/global.php

Bạn chỉ cần thêm một phần tử db là mảng cấu hình Adapter trên

return [
//...
    'db' = [
        'driver'   => 'Mysqli',
        'username' => 'root',
        'password' => '',
        'database' => 'xtdb',
    ];
//...
];

Nếu có cấu hình trên, thì đối tượng Zend\Db\Adapter\Adapter có được mỗi khi ấn dụng cần chỉ cần gọi:

$adapter = $servicemanager->get(\Zend\Db\Adapter\Adapter::class);

Ví dụ sử dụng Adapter như Service

Bước 1) Bạn hãy cập nhật config/autoload/global.php như trên theo đúng thông số kết nối đến CSDL cấu hình của bạn (ở đây sử dụng dữ liệu mẫu xtdb tải ở trên).

Bước 2) Thiết lập controller Index như là một factory như hướng dẫn tại Đăng ký controller, bằng cách triển khai thêm phương thức __invoke($container), đồng thời thêm một biến thuộc tính $servicemanager

module/Application/src/Controller/IndexController.php

//...
class IndexController extends AbstractActionController
{
    protected $servicemanager;

    public function __invoke($container)
    {
        //Lưu Service Manager
        $this->servicemanager = $container;
        return $this;
    }

 //...

Sau đó mở file module/Application/config/module.config.php thay dòng Controller\IndexController::class => InvokableFactory::class bằng Controller\IndexController::class => Controller\IndexController::class

Bước 3) Tạo thử phương thức testadapter để kiểm tra

module/Application/src/Controller/IndexController.php

//...
public function testadapterAction() {

    $adapter = $this->servicemanager
                ->get(\Zend\Db\Adapter\Adapter::class);
    return $this->getResponse()
                ->setContent('Cơ sở dữ liệu:'.$adapter->getCurrentSchema());

}
 //...

Kiểm tra với URL: http://localhost/zend-db/application/testadapter

Kết quả hiện ra: Cơ sở dữ liệu:xtdb

Đăng ký theo dõi ủng hộ kênh