You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
11 KiB
252 lines
11 KiB
9 years ago
|
Làm việc với CSDL
|
||
|
======================
|
||
|
|
||
|
Phần này sẽ hướng dẫn làm thế nào để tạo mới trang có chức năng hiển thị dữ liệu các thành phố (country) và được lấy
|
||
|
từ bảng `country` nằm trong cơ sở dữ liệu. Để thực hành tốt bài hướng dẫn, bạn cần cấu hình các kết nối tới CSDL,
|
||
|
tạo class [Active Record](db-active-record.md), taọ một [action](structure-controllers.md),
|
||
|
và tạo mới [view](structure-views.md).
|
||
|
|
||
|
Tóm tắt những nội dung chính:
|
||
|
|
||
|
* Cấu hình kết nối tới CSDL
|
||
|
* Đinh nghĩa lớp Active Record
|
||
|
* Sử dụng lớp Active Record để truy vấn dữ liệu
|
||
|
* Hiển thị và phân trang dữ liệu trên view
|
||
|
|
||
|
Lưu ý để thực hiện được bài hướng dẫn này, bạn cần có kiến thức về CSDL.
|
||
|
Riêng ở phần này, bạn cần có kiến thức về tạo mới CSDL, và làm thế nào để thực thi các câu lệnh SQL sử dụng công cụ ở phía client.
|
||
|
|
||
|
|
||
|
Chuẩn bị <span id="preparing-database"></span>
|
||
|
----------------------
|
||
|
|
||
|
Đầu tiên, bạn cần tạo mới CSDL tên là `yii2basic`, từ bây giờ bạn sẽ dùng CSDL này để lấy dữ liệu.
|
||
|
Yii hỗ trợ nhiều CSDL trong ứng dụng, bạn có thể dùng những CSDL như SQLite, MySQL, PostgreSQL, MSSQL hoặc Oracle. Để cho đơn giản,
|
||
|
MySQL sẽ được dùng trong bài hướng dẫn này.
|
||
|
|
||
|
Tiếp đến, tạo mới bảng vào CSDL tên là `country` , đồng thời chèn thêm dữ liệu. You may run the following SQL statements to do so:
|
||
|
|
||
|
```sql
|
||
|
CREATE TABLE `country` (
|
||
|
`code` CHAR(2) NOT NULL PRIMARY KEY,
|
||
|
`name` CHAR(52) NOT NULL,
|
||
|
`population` INT(11) NOT NULL DEFAULT '0'
|
||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||
|
|
||
|
INSERT INTO `country` VALUES ('AU','Australia',18886000);
|
||
|
INSERT INTO `country` VALUES ('BR','Brazil',170115000);
|
||
|
INSERT INTO `country` VALUES ('CA','Canada',1147000);
|
||
|
INSERT INTO `country` VALUES ('CN','China',1277558000);
|
||
|
INSERT INTO `country` VALUES ('DE','Germany',82164700);
|
||
|
INSERT INTO `country` VALUES ('FR','France',59225700);
|
||
|
INSERT INTO `country` VALUES ('GB','United Kingdom',59623400);
|
||
|
INSERT INTO `country` VALUES ('IN','India',1013662000);
|
||
|
INSERT INTO `country` VALUES ('RU','Russia',146934000);
|
||
|
INSERT INTO `country` VALUES ('US','United States',278357000);
|
||
|
```
|
||
|
|
||
|
Đến đây, bạn có CSDL là `yii2basic`, có chứa bảng `country` có 3 cột và 10 trường dữ liệu.
|
||
|
|
||
|
Cấu hình kết nối tới CSDL <span id="configuring-db-connection"></span>
|
||
|
---------------------------
|
||
|
|
||
|
Trước tiên, hãy chắc chắn rằng bạn đã cài 2 gói PHP [PDO](http://www.php.net/manual/en/book.pdo.php) và
|
||
|
PDO driver dành cho các CSDL mà đang sử dụng(ví dụ `pdo_mysql` cho MySQL). Đối với các CSDL quan hệ thì những gói này
|
||
|
cần phải có.
|
||
|
|
||
|
Sau khi những yêu cầu trên được cài đặt, mở file `config/db.php` và thay đổi các tham số chính xác tới CSDL. Mặc định,
|
||
|
file sẽ có những đoạn code sau:
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
|
||
|
return [
|
||
|
'class' => 'yii\db\Connection',
|
||
|
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
|
||
|
'username' => 'root',
|
||
|
'password' => '',
|
||
|
'charset' => 'utf8',
|
||
|
];
|
||
|
```
|
||
|
|
||
|
File `config/db.php` là file điển hình dành cho cấu hình ứng dụng [configuration](concept-configurations.md). Các tham số được mô tả trong file
|
||
|
cần thiết để tạo mới và khởi tạo các thể hiện [[yii\db\Connection]] và thực hiện các câu lệnh truy vấn
|
||
|
|
||
|
Các thông tin cấu hình về CSDL ở trên được truy cập qua ứng dụng qua câu lệnh `Yii::$app->db`.
|
||
|
|
||
|
> Lưu ý: File `config/db.php` sẽ chứa các thông tin chính trong việc cấu hình ứng dụng `config/web.php`,
|
||
|
Những thông tin làm thế nào để [ứng dụng](structure-applications.md) cần được khởi tạo.
|
||
|
Bạn có thể tham khảo thêm trong phần [cấu hình ứng dụng](concept-configurations.md) .
|
||
|
|
||
|
|
||
|
Tạo mới class Active Record <span id="creating-active-record"></span>
|
||
|
-------------------------
|
||
|
|
||
|
Để thể hiện và thao tác với bảng dữ liệu `country`, ta tạo mới class[Active Record](db-active-record.md)-
|
||
|
tên là `Country`, và lưu vào file `models/Country.php`.
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
|
||
|
namespace app\models;
|
||
|
|
||
|
use yii\db\ActiveRecord;
|
||
|
|
||
|
class Country extends ActiveRecord
|
||
|
{
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Lớp `Country` được kế thừa từ [[yii\db\ActiveRecord]]. Bạn không cần viết bất kỳ đoạn mã nào vào phần này! Chỉ với đoạn mã trên,
|
||
|
Yii sẽ biết được tên bảng từ tên của lớp tương ứng.
|
||
|
|
||
|
> Info: Nếu tên lớp không trùng với tên trong bảng dữ liệu, bạn có thể
|
||
|
ghi đè phương thức [[yii\db\ActiveRecord::tableName()]] để miêu tả rõ ràng về tên bảng dữ liệu.
|
||
|
|
||
|
Dùng lớp `Country`, bạn sẽ dễ dàng hơn trong việc thao tác với bảng `country`, ví dụ:
|
||
|
|
||
|
```php
|
||
|
use app\models\Country;
|
||
|
|
||
|
// lấy danh sách tử bảng country và sắp xếp theo thuộc tính "name"
|
||
|
$countries = Country::find()->orderBy('name')->all();
|
||
|
|
||
|
// lấy dữ liệu có khóa là "US"
|
||
|
$country = Country::findOne('US');
|
||
|
|
||
|
// in kết quả "United States"
|
||
|
echo $country->name;
|
||
|
|
||
|
// thay đổi tên country thành "U.S.A." và lưu vào csdl
|
||
|
$country->name = 'U.S.A.';
|
||
|
$country->save();
|
||
|
```
|
||
|
|
||
|
> Lưu ý: Active Record khá là mạnh cho việc truy cập csdl theo hướng lập trình hướng đối tượng.
|
||
|
Bạn có thể xem thêm ở mục [Active Record](db-active-record.md). Cách khác, bạn có thể thao tác với csdl ở mức độ đơn giản hơn bằng việc truy cập qua đối tượng [Data Access Objects](db-dao.md).
|
||
|
|
||
|
|
||
|
Tạo hành động (action) <span id="creating-action"></span>
|
||
|
------------------
|
||
|
|
||
|
Để hiển thị dữ liệu country tới người dùng, bạn cần tạo mới hành động. Thay vì đặt các hành động ở `site`
|
||
|
controller, giống như đã làm ở phần trước, thì tạo controller mới có ý nghĩa hơn
|
||
|
đặc biệt liên quan tới dữ liệu về coutry. Tên controller là `CountryController`, và tạo mới
|
||
|
hành động `index` ở trong đó, bạn có thể tham khảo ở phần dưới.
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
|
||
|
namespace app\controllers;
|
||
|
|
||
|
use yii\web\Controller;
|
||
|
use yii\data\Pagination;
|
||
|
use app\models\Country;
|
||
|
|
||
|
class CountryController extends Controller
|
||
|
{
|
||
|
public function actionIndex()
|
||
|
{
|
||
|
$query = Country::find();
|
||
|
|
||
|
$pagination = new Pagination([
|
||
|
'defaultPageSize' => 5,
|
||
|
'totalCount' => $query->count(),
|
||
|
]);
|
||
|
|
||
|
$countries = $query->orderBy('name')
|
||
|
->offset($pagination->offset)
|
||
|
->limit($pagination->limit)
|
||
|
->all();
|
||
|
|
||
|
return $this->render('index', [
|
||
|
'countries' => $countries,
|
||
|
'pagination' => $pagination,
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Lưu nội dung đoạn mã trên vào file `controllers/CountryController.php`.
|
||
|
|
||
|
Hành động `index` sẽ gọi các phương thức `Country::find()`. Đây là phương thức nằm ở Active Record nhằm xây dựng câu lệnh truy vấn và lấy tất cả dữ liệu trong bảng `country`.
|
||
|
Để hạn chế số lượng dữ liệu mỗi khi gửi yêu cầu, đối tượng [[yii\data\Pagination]] sẽ phân trang dữ liệu.
|
||
|
Mục đích khi dùng đối tượng `Pagination` là:
|
||
|
|
||
|
* Thiết lập điều kiện `offset` và `limit` cho câu lệnh mỗi khi lấy liệu ra (mỗi lần chỉ hiển thị 5 kết quả).
|
||
|
* Dữ liệu được nhúng vào view để hiển thị số trang và bao gồm danh sách các button, sẽ được giải thích ở phần sau.
|
||
|
|
||
|
Xem những dòng cuối, hành động `index` sẽ đổ ra view có tên là `index`, đồng thời gửi dữ liệu về country và thông tin về phân trang.
|
||
|
|
||
|
|
||
|
Tạo View <span id="creating-view"></span>
|
||
|
---------------
|
||
|
|
||
|
Trong thư mục `views`, bước một tạo thư mục con là `country`. Thư mực này được dùng để giữ những view được đổ ra
|
||
|
từ controller `country`. Trong thư mục `views/country`, tạo mới file tên là `index.php`
|
||
|
và chứa đoạn mã sau:
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
use yii\helpers\Html;
|
||
|
use yii\widgets\LinkPager;
|
||
|
?>
|
||
|
<h1>Countries</h1>
|
||
|
<ul>
|
||
|
<?php foreach ($countries as $country): ?>
|
||
|
<li>
|
||
|
<?= Html::encode("{$country->name} ({$country->code})") ?>:
|
||
|
<?= $country->population ?>
|
||
|
</li>
|
||
|
<?php endforeach; ?>
|
||
|
</ul>
|
||
|
|
||
|
<?= LinkPager::widget(['pagination' => $pagination]) ?>
|
||
|
```
|
||
|
|
||
|
View trên có 2 phần liên quan tới hiển thị dữ liệu về country. Phần đầu tiên, cung cấp danh sách country và in ra dưới dạng danh sách .
|
||
|
Phần tiếp, một widget [[yii\widgets\LinkPager]] được sinh ra và dùng các thông tin truyển từ action xuống để phân trang.
|
||
|
Đối tượng `LinkPager` là một widget có chức năng hiển thị danh sách các button. Mỗi khi click vào mỗi button này sẻ cập nhật lại dữ liệu country
|
||
|
ở mỗi trang tương ứng.
|
||
|
|
||
|
|
||
|
Xem demo <span id="trying-it-out"></span>
|
||
|
-------------
|
||
|
|
||
|
Truy cập vào Url sau và xem kết quả:
|
||
|
|
||
|
```
|
||
|
http://hostname/index.php?r=country/index
|
||
|
```
|
||
|
|
||
|
![Danh sách Country](images/start-country-list.png)
|
||
|
|
||
|
Hãy xem, bạn sẽ thấy một trang hiển thị 4 country. Phần dưới danh sách các country, bạn sẽ thấy các nút phân trang.
|
||
|
Nếu bạn click vào button "2", bạn sẽ thấy 5 country khác trong CSDL: trang thứ 2 trong CSDL country.
|
||
|
Bạn để ý rằng URL trong trình duyệt cũng thay đổi.
|
||
|
|
||
|
```
|
||
|
http://hostname/index.php?r=country/index&page=2
|
||
|
```
|
||
|
|
||
|
Trong luồng xử lý này, đối tượng [[yii\data\Pagination|Pagination]] sẽ cung cấp tất cả những hàm cần thiết cho việc phân trang:
|
||
|
|
||
|
* Khởi tạo, đối tượng [[yii\data\Pagination|Pagination]] hiển thị ở trang đầu tiên , điều này được thực hiện câu lệnh truy vấn SELECT từ country
|
||
|
với mệnh đề `LIMIT 5 OFFSET 0`. Như kết quả trên, 5 country đầu tiên sẽ lấy ra và hiển thị.
|
||
|
* Widget [[yii\widgets\LinkPager|LinkPager]] sẽ tạo các buttons cùng với các URL( liên kết)
|
||
|
được tạo bởi phương thức [[yii\data\Pagination::createUrl()|Pagination]]. Các URL sẽ chứa tham số `page`, page sẽtương ứng với số trang khác nhau trong CSDL country.
|
||
|
* Nếu bạn click vào button "2", route `country/index` được gọi và đồng thời route sẽ được gắn và giữ.
|
||
|
Đối tượng [[yii\data\Pagination|Pagination]] đọc số trang từ tham số `page` từ Url và thiết lập trang trang hiện tại là 2.
|
||
|
Việc truy vấn dữ liệu country tương tự như mệnh đề `LIMIT 5 OFFSET 5` và trả về tiếp 5 country để hiển thị
|
||
|
|
||
|
|
||
|
Tổng kết <span id="summary"></span>
|
||
|
-------
|
||
|
|
||
|
Bài hướng dẫn này, giúp bạn tìm hiểu và làm việc với CSDL. Bạn cũng được tìm hiều đối tượng [[yii\data\Pagination]] và [[yii\widgets\LinkPager]]. giúp cho việc
|
||
|
lấy và hiển thì dữ liệu trên trang.
|
||
|
|
||
|
Trong phần tới, bạn sẽ được tìm hiểu về công cụ generate code khá mạnh, được gọi là [Gii](tool-gii.md),
|
||
|
giúp bạn nhanh chóng thực hiện một số tính năng tương tự, những hoạt động thao tác với các bảng trong CSDL như Tạo-Xem-Cập nhật-Xóa (CRUD)
|
||
|
. Trong thực tế, những mã nguồn được viết có thể tự động generate trong Yii sử dụng công cụ Gii.
|