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ị ---------------------- Đầ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 --------------------------- 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 '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 ------------------------- Để 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 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) ------------------ Để 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 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 --------------- 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