start-databases.md 15.4 KB
Newer Older
metheoryt committed
1 2 3 4 5 6 7 8 9 10
Работа с базами данных 
======================

Этот раздел расскажет о том, как создать новую страницу, отображающую данные по странам, полученные из таблицы `countries` базы данных. Для достижения этой цели вам будет необходимо настроить подключение к базе данных, создать класс [Active Record](db-active-record.md), определить [action](structure-controllers.md), и создать [view](structure-views.md).

Изучив эту часть, вы научитесь:

* Настраивать подключение к БД
* Определять класс Active Record
* Запрашивать данные, используя класс Active Record
11
* Отображать данные во view с использованием пагинации
metheoryt committed
12 13 14 15 16 17 18 19 20 21 22

Обратите внимание, чтобы усвоить этот раздел, вы должны иметь базовые знания и навыки использования баз данных. 
В частности, вы должны знать, как создать базу данных, и как выполнять SQL запросы, используя клиентские инструменты для работы с БД.

Подготавливаем базу данных <a name="preparing-database"></a>
----------------------

Для начала, создайте базу данных под названием `yii2basic`, из которой вы будете получать данные в вашем приложении.
Вы можете создать базу данных SQLite, MySQL, PostgreSQL, MSSQL или Oracle, так как Yii имеет встроенную поддержку для многих баз данных. Для простоты, в дальнейшем описании будет подразумеваться MySQL.

После этого создайте в базе данных таблицу `country`, и добавьте в неё немного демонстрационных данных. Вы можете запустить следующую SQL инструкцию, чтобы сделать это:
23

metheoryt committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
```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` с тремя столбцами, содержащими десять строк данных.

Настраиваем подключение к БД <a name="configuring-db-connection"></a>
---------------------------

48 49
Перед продолжением убедитесь, что у вас установлены PHP-расширение [PDO](http://www.php.net/manual/en/book.pdo.php) и драйвер PDO для используемой вами базы данных (н-р `pdo_mysql` для MySQL). Это базовое требование в случае использования вашим приложением реляционной базы данных.
После того, как они установлены, откройте файл `config/db.php` и измените параметры на верные для вашей базы данных. По умолчанию этот файл содержит следующее:
metheoryt committed
50 51 52 53 54 55 56 57 58 59 60 61 62

```php
<?php

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=yii2basic',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
];
```

63
Файл `config/db.php` - типичный [конфигурационный](concept-configurations.md) инструмент, базирующийся на файлах. Данный конфигурационный файл определяет параметры, необходимые для создания и инициализации экземпляра [[yii\db\Connection]], через который вы можете делать SQL запросы к подразумеваемой базе данных.
metheoryt committed
64

65
Подключение к БД, настроенное выше, доступно в коде приложения через выражение `Yii::$app->db`.
metheoryt committed
66

67 68 69
> Информация: файл `config/db.php` будет подключен главной конфигурацией приложения `config/web.php`,
  описывающей то, как экземпляр [приложения](structure-applications.md) должен быть инициализирован.
  Для детальной информации, пожалуйста, обратитесь к разделу [Конфигурации](concept-configurations.md).
metheoryt committed
70

71
Создаём потомка Active Record <a name="creating-active-record"></a>
metheoryt committed
72 73
-------------------------

74
Чтобы представлять и получать данные из таблицы `country`, создайте класс - потомок [Active Record](db-active-record.md), под названием `Country`, и сохраните его в файле `models/Country.php`.
metheoryt committed
75 76 77 78 79 80 81 82 83 84 85 86 87

```php
<?php

namespace app\models;

use yii\db\ActiveRecord;

class Country extends ActiveRecord
{
}
```

88
Класс `Country` наследуется от [[yii\db\ActiveRecord]]. Вам не нужно писать ни строчки кода внутри него! С кодом, приведённым выше, Yii свяжет имя таблицы с именем класса.
metheoryt committed
89

90 91
> Информация: Если нет возможности задать прямой зависимости между именем таблицы и именем класса, вы можете переопределить
  метод [[yii\db\ActiveRecord::tableName()]], чтобы явно задать имя связанной таблицы.
metheoryt committed
92

93
Используя класс `Country`, вы можете легко манипулировать данными в таблице `country`, как показано в этих фрагментах:
metheoryt committed
94 95 96 97

```php
use app\models\Country;

98
// получаем все строки из таблицы "country" и сортируем их по "name"
metheoryt committed
99 100
$countries = Country::find()->orderBy('name')->all();

101
// получаем строку с первичным ключом "US"
metheoryt committed
102 103
$country = Country::findOne('US');

104
// отобразит "United States"
metheoryt committed
105 106
echo $country->name;

107
// меняем имя страны на "U.S.A." и сохраняем в базу данных
metheoryt committed
108 109 110 111
$country->name = 'U.S.A.';
$country->save();
```

112 113
> Информация: Active Record - мощный способ доступа и манипулирования данными БД в объектно-ориентированном стиле.
  Вы можете найти подробную информацию в разделе [Active Record](db-active-record.md). В качестве альтернативы, вы также можете взаимодействовать с базой данных, используя более низкоуровневый способ доступа, называемый [Data Access Objects](db-dao.md).
metheoryt committed
114 115


116
Создаём Action <a name="creating-action"></a>
metheoryt committed
117 118
------------------

119
Для того, чтобы показать данные по странам конечным пользователям, вам надо создать новый action. Вместо размещения нового action'a в контроллере `site`, как вы делали в предыдущих разделах, будет иметь больше смысла создать новый контроллер специально для всех действий, относящихся к данным по странам. Назовите новый контроллер `CountryController`, и создайте action `index` внутри него, как показано ниже.
metheoryt committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

```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,
        ]);
    }
}
```

154
Сохраните код выше в файле `controllers/CountryController.php`.
metheoryt committed
155

156 157 158 159
Action `index` вызывает `Country::find()`. Данный метод Active Record строит запрос к БД и извлекает все данные из таблицы `country`.
Чтобы ограничить количество стран, возвращаемых каждым запросом, запрос разбивается на страницы с помощью объекта [[yii\data\Pagination]]. Объект `Pagination` служит двум целям:
* Устанавливает пункты `offset` и `limit` для SQL инструкции, представленной запросом, чтобы она возвращала только одну страницу данных за раз (в нашем случае максимум 5 строк на страницу).
* Он используется во view для отображения пагинатора, состоящего из набора кнопок с номерами страниц, это будет разъяснено в следующем подразделе.
metheoryt committed
160

161
В конце кода action `index` выводит view с именем `index`, и передаёт в него данные по странам вместе c информацией о пагинации.
metheoryt committed
162

163
Создаём View <a name="creating-view"></a>
metheoryt committed
164 165
---------------

166
Первым делом создайте поддиректорию с именем `country` внутри директории `views`. Эта папка будет использоваться для хранения всех view, выводимых контроллером `country`. Внутри директории `views/country` создайте файл с именем `index.php`, содержащий следующий код:
metheoryt committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

```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]) ?>
```

186 187
View имеет 2 части относительно отображения данных по странам. В первой части предоставленные данные по странам выводятся как неупорядоченный HTML-список.
Во второй части выводится виджет [[yii\widgets\LinkPager]], используя информацию о пагинации, переданную из action во view. Виджет `LinkPager` отображает набор постраничных кнопок. Клик по любой из них обновит данные по странам в соответствующей странице.
metheoryt committed
188 189


190
Испытываем в действии <a name="trying-it-out"></a>
metheoryt committed
191 192
-------------

193
Чтобы увидеть, как работает весь вышеприведённый код, перейдите по следующей ссылке в своём браузере:
metheoryt committed
194 195 196 197 198

```
http://hostname/index.php?r=country/index
```

199
![Список Стран](images/start-country-list.png)
metheoryt committed
200

201 202
В начале вы увидите страницу, показывающую пять стран. Под странами вы увидите пагинатор с четырьмя кнопками. Если вы кликните по кнопке "2", то увидите страницу, отображающую другие пять стран из базы данных: вторая страница записей.
Посмотрев внимательней, вы увидите, что URL в браузере тоже сменилось на
metheoryt committed
203 204 205 206 207

```
http://hostname/index.php?r=country/index&page=2
```

208 209 210 211
За кадром, [[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`. Таким образом новый запрос стран будет иметь параметры `LIMIT 5 OFFSET 5` и вернет следующие пять стран для отображения.
metheoryt committed
212

213
Резюме <a name="summary"></a>
metheoryt committed
214 215
-------

216
В этом разделе вы научились работать с базой данных. Также вы научились получать и отображать данные с постраничной разбивкой с помощью [[yii\data\Pagination]] и [[yii\widgets\LinkPager]].
metheoryt committed
217

218
В следующем разделе вы научитесь использовать мощный инструмент генерации кода, называемый [Gii](tool-gii.md), чтобы с его помощью быстро осуществлять некоторые частоиспользуемые функции, такие, как операции Create-Read-Update-Delete (CRUD) для работы с данными в таблице базы данных. На самом деле код, который вы только что написали, в Yii может быть полностью сгенерирован автоматически с использованием Gii.