mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-01 03:26:36 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			252 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 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',24016400);
 | |
| INSERT INTO `country` VALUES ('BR','Brazil',205722000);
 | |
| INSERT INTO `country` VALUES ('CA','Canada',35985751);
 | |
| INSERT INTO `country` VALUES ('CN','China',1375210000);
 | |
| INSERT INTO `country` VALUES ('DE','Germany',81459000);
 | |
| INSERT INTO `country` VALUES ('FR','France',64513242);
 | |
| INSERT INTO `country` VALUES ('GB','United Kingdom',65097000);
 | |
| INSERT INTO `country` VALUES ('IN','India',1285400000);
 | |
| INSERT INTO `country` VALUES ('RU','Russia',146519759);
 | |
| INSERT INTO `country` VALUES ('US','United States',322976000);
 | |
| ```
 | |
| 
 | |
| Đế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](https://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ả:
 | |
| 
 | |
| ```
 | |
| https://hostname/index.php?r=country/index
 | |
| ```
 | |
| 
 | |
| 
 | |
| 
 | |
| 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.
 | |
| 
 | |
| ```
 | |
| https://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.
 | 
