Робота з базами даних
=====================
Цей розділ описує, як створити нову сторінку, яка буде відображати дані країни, отримані з
таблиці `country` бази даних. Для цього, вам необхідно буде налаштувати зʼєднання з базою даних,
створити клас [Active Record ](db-active-record.md ), визначити [дію ](structure-controllers.md )
та створити [представлення ](structure-views.md ).
В даному розділі ви дізнаєтесь як:
* налаштувати зʼєднання з базою даних;
* визначити клас Active Record;
* запитувати дані за допомогою класу Active Record;
* відображати дані у представленні із розділенням на сторінки.
Зверніть увагу, що для того, щоб закінчити цей розділ, ви повинні мати базові знання і досвід використання баз даних.
Зокрема, ви повинні знати, як створювати бази даних та як виконувати SQL-запити за допомогою клієнтських додатків баз даних.
Підготовка бази даних < span id = "preparing-database" > < / span >
---------------------
Для початку, створіть базу даних `yii2basic` , з якої і будете надалі отримувати дані.
Ви можете створити базу даних SQLite, MySQL, PostgreSQL, MSSQL або Oracle, Yii має вбудовану підтримку для багатьох баз даних.
Для простоти, у подальшому описі будемо вважати що використовується MySQL.
Далі, створіть таблицю `country` у базі даних, і внесіть декілька зразків даних. Можете використати наступний SQL-запит, як приклад:
```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);
```
На даний момент, у вас є база даних `yii2basic` і таблиця `country` з трьома колонками, що містить десять рядків даних.
Налаштування підключення до БД < span id = "configuring-db-connection" > < / span >
------------------------------
Перш ніж продовжити, переконайтеся, що у вас встановлено розширення PHP [PDO ](http://www.php.net/manual/en/book.pdo.php )
та драйвер PDO для вашої БД (наприклад `pdo_mysql` для MySQL). Це є основною вимогою,
якщо ваш додаток використовує реляційну базу даних.
Коли вони встановлені, відкрийте файл `config/db.php` і змініть параметри для відповідності вашій БД.
За замовчуванням, файл містить наступне:
```php
< ?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
];
```
Файл конфігурації `config/db.php` є типовим інструментом [налаштування ](concept-configurations.md ) на основі файлів.
Даний файл конфігурації визначає параметри, які необхідні для створення та ініціалізації екземпляру [[yii\db\Connection]],
через який ви можете робити SQL-запити до зазначеної бази даних.
З’єднання з БД, описане вище, може бути доступне в коді додатка за допомогою виразу `Yii::$app->db` .
> Інформація: Файл конфігурації `config/db.php` буде включений до конфігурації головного додатка `config/web.php`,
який визначає як має бути проініціалізований екземпляр [додатку ](structure-applications.md ).
Для отримання додаткової інформації, будь ласка, зверніться до розділу [Конфігурації ](concept-configurations.md ).
Створення Active Record < span id = "creating-active-record" > < / span >
-----------------------
Для репрезентації та отримання даних з таблиці `country` створіть похідний від [Active Record ](db-active-record.md )
клас з іменем `Country` , і збережіть його в файл `models/Country.php` .
```php
< ?php
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
}
```
Клас `Country` наслідує [[yii\db\ActiveRecord]]. Вам не потрібно писати ніякого коду всередині нього!
Всього лише за допомогою описаного вище коду, Yii самостійно вгадає відповідне імʼя таблиці з імені класу.
> Інформація: Якщо неможливо отримати прямої відповідності імені класу до імені таблиці, ви можете
перевизначити метод [[yii\db\ActiveRecord::tableName()]], щоб точно задати відповідне імʼя таблиці.
Використовуючи клас `Country` , ви можете легко маніпулювати даними з таблиці `country` , як показано у цих фрагментах коду:
```php
use app\models\Country;
// отримати всі рядки з таблиці country і відсортувати їх по "name"
$countries = Country::find()->orderBy('name')->all();
// отримати рядок, по основному ключу "US"
$country = Country::findOne('US');
// відобразити "United States"
echo $country->name;
// змінити назву країни на "U.S.A." і зберегти в БД
$country->name = 'U.S.A.';
$country->save();
```
> Інформація: Active Record є потужним засобом для доступу і управління даними бази даних в обʼєктно-орієнтованому стилі.
Ви можете знайти більш детальну інформацію в розділі [Active Record ](db-active-record.md ). Крім того, ви також можете
взаємодіяти з базою даних, використовуючи для доступу метод передачі даних нижнього рівня під назвою [Data Access Objects ](db-dao.md ).
Створення дії < span id = "creating-action" > < / span >
-------------
Щоб відобразити дані про країну кінцевим користувачам, необхідно створити нову дію. Замість розміщення нової дії
у контролері `site` , який ви використовували в попередніх розділах, є сенс створити новий контролер спеціально для всіх дій,
пов’язаних з даними країн. Створіть новий контролер з іменем `CountryController` і дію `index` , як показано нижче:
```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,
]);
}
}
```
Збережіть цей код у файл `controllers/CountryController.php` .
Дія `index` викликає метод `Country::find()` . Цей метод Active Record будує запит до бази даних і отримує всі дані з таблиці `country` .
Щоб обмежити кількість країн, які будуть отримуватись в кожному запиті, сам запит розділяється на сторінки, за допомогою об’єкта
[[yii\data\Pagination]]. Об’єкт `Pagination` служить двом цілям:
* Встановлює директиви `offset` і `limit` для SQL-запиту так, щоб він повертав лише одну сторінку даних за один раз
(не більше 5 рядків на сторінці).
* Використовується у представленнях для відображення пейджера, який складається із переліку кнопок переходу по сторінках,
про що буде описано у наступному підрозділі.
Наприкінці, дія `index` формує представлення з іменем `index` та передає до нього дані по країнах із інформацією про посторінкове
розділення.
Створення представлення < span id = "creating-view" > < / span >
-----------------------
В директорії `views` створіть спочатку під-директорію `country` . Цей каталог буде використовуватись для всіх
представлень контролера `country` . В директорії `views/country` , створіть файл з іменем `index.php` ,
що містить наступне:
```php
< ?php
use yii\helpers\Html;
use yii\widgets\LinkPager;
?>
< h1 > Країни< / h1 >
< ul >
<?php foreach ($countries as $country): ?>
< li >
<?= Html::encode("{$country->name} ({$country->code})") ?> :
<?= $country->population ?>
< / li >
<?php endforeach; ?>
< / ul >
<?= LinkPager::widget(['pagination' => $pagination]) ?>
```
Дане представлення містить дві секції для відображення даних про країни. У першій частині, відображаються передані дані про країни
у вигляді невпорядкованого списку HTML. У другій частині, віджет [[yii\widgets\LinkPager]] з використанням інформації
про нумерацію сторінок. Віджет `LinkPager` відображається у вигляді переліку кнопок.
При натисканні на будь-якій з них будуть виводитись дані країн для відповідної сторінки.
Спробуємо < span id = "trying-it-out" > < / span >
---------
Щоб побачити як весь вищезазначений код працює, відкрийте в браузері наступний URL:
```
http://hostname/index.php?r=country/index
```
![Перелік країн ](images/start-country-list.png )
Спочатку, ви побачите сторінку з переліком пʼяти країн. Нижче країн, ви побачите пейджер з чотирма кнопками.
Якщо ви натиснете на кнопку "2", ви побачите сторінку з іншими пʼятьма країнами з бази даних: другу сторінку записів.
Придивившись більш уважно, ви побачите, що URL в браузері також змінюється на
```
http://hostname/index.php?r=country/index& page=2
```
За лаштунками, [[yii\data\Pagination|Pagination]] надає всю необхідну функціональність для розділення набору даних на сторінки:
* Спочатку, [[yii\data\Pagination|Pagination]] представляє першу сторінку, яка відображає країни запитом SELECT
з умовою `LIMIT 5 OFFSET 0` . В результаті, будуть відображені перші знайдені пʼять країн.
* Віджет [[yii\widgets\LinkPager|LinkPager]] відображає кнопки сторінок з URL-адресами створеними за допомогою
[[yii\data\Pagination::createUrl()|Pagination]]. URL-адреси будуть містити параметр запиту `page` ,
який представляє різні номери сторінок.
* Якщо натиснути кнопку "2", новий запит для маршруту `country/index` спрацьовує і обробляється.
[[yii\data\Pagination|Pagination]] зчитає параметр `page` з URL-запиту і встановить для поточної сторінки номер 2.
Таким чином, новий запит до БД буде мати умову `LIMIT 5 OFFSET 5` і поверне наступні пʼять країн для відображення.
Підсумок < span id = "summary" > < / span >
--------
В цьому розділі ви дізналися, як працювати з базою даних. Ви також дізналися, як вибирати і відображати дані на сторінках
за допомогою [[yii\data\Pagination]] і [[yii\widgets\LinkPager]].
У наступному розділі ви дізнаєтеся, як використовувати потужний інструмент генерування коду, що називається [Gii ](https://github.com/yiisoft/yii2-gii/blob/master/docs/guide-uk/README.md ),
який допоможе вам швидко створювати деякі часто необхідні функції, такі як Create-Read-Update-Delete (CRUD)
операції для роботи з даними в таблицях баз даних. Насправді, код, який ви щойно написали,
в Yii можливо автоматично згенерувати за допомогою інструменту Gii.