yakoffka.ru
    грабли, костыли и велосипеды php, css, html, js и прочего

    Yii 2.0 часть 2. Работа с базами данных

    YiiYii 2.0. конспект-памятка курса 'Полное руководство по Yii 2.0' с незначительными вариациями. Оригинал на русском языке можно найти здесь.

    АЛАРМА!!! Данная памятка являет собой откровенный копипаст! Для ознакомления с первоисточником перейдите по ссылке, указанной выше.

    копипастил Капустин Яков

    оглавление

    Создадим новую страницу, отображающую данные по странам, полученные из таблицы countries базы данных (необходимо настроить подключение к базе данных, создать класс Active Record, определить action и создать view).

    Подготовка базы данных

    Для начала создадим базу данных под названием yii2basic, используя MySQL.

    1. Переходим в phpmyadmin;
    2. Создаём новую базу данных yii2basic, указав ей сравнение utf8_unicode_ci;
    3. Создаём в базе данных таблицу country;
    4. Переходим на вкладку SQL;
    5. Вставляем представленный ниже код запроса и выполняем его
    6. Теперь мы имеем базу данных yii2basic с таблицей country с тремя столбцами, содержащими десять строк данных.
    код запуска SQL инструкции для создания в базе данных таблицы country:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18

    CREATE TABLE 
    `country` (
      `
    codeCHAR(2NOT NULL PRIMARY KEY,
      `
    nameCHAR(52NOT NULL,
      `
    populationINT(11NOT NULL DEFAULT '0'
    ENGINE=InnoDB DEFAULT CHARSET=utf8;

    INSERT INTO `countryVALUES ('AU','Australia',24016400);
    INSERT INTO `countryVALUES ('BR','Brazil',205722000);
    INSERT INTO `countryVALUES ('CA','Canada',35985751);
    INSERT INTO `countryVALUES ('CN','China',1375210000);
    INSERT INTO `countryVALUES ('DE','Germany',81459000);
    INSERT INTO `countryVALUES ('FR','France',64513242);
    INSERT INTO `countryVALUES ('GB','United Kingdom',65097000);
    INSERT INTO `countryVALUES ('IN','India',1285400000);
    INSERT INTO `countryVALUES ('RU','Russia',146519759);
    INSERT INTO `countryVALUES ('US','United States',322976000);
      
    Рис. 1 Выполнение SQL-запроса из phpmyadmin
    Рис. 1 Выполнение SQL-запроса из phpmyadmin

    Настраиваем подключение к БД

    Я верю, что у меня установлены PHP-расширение PDO и драйвер PDO для используемой базы данных (pdo_mysql для MySQL),по этому просто открываю файл config/db.php и проверяю параметры базы данных:

    Содержимое config/db.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    <?php

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

          
    // Schema cache options (for production environment)
          //'enableSchemaCache' => true,
          //'schemaCacheDuration' => 60,
          //'schemaCache' => 'cache',
      
    ];
      

    Подключение к БД, настроенное выше, доступно в коде приложения через выражение Yii::$app->db. Файл config/db.php будет подключен главной конфигурацией приложения config/web.php, описывающей то, как экземпляр приложения должен быть инициализирован.

    Создаём потомка Active Record

    Чтобы представлять и получать данные из таблицы country, в файле models/Country.php создадим класс Country — потомок Active Record. Yii сам свяжет имя таблицы с именем класса. Если нет возможности задать прямую зависимость между именем таблицы и именем класса, можно переопределить метод yii\db\ActiveRecord::tableName(), чтобы явно задать имя связанной таблицы.

    models/Country.php:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
        
    namespace app\models;

        use 
    yii\db\ActiveRecord;

        class 
    Country extends ActiveRecord{

        }
      
    пример манипулирования данными в таблице с использованием класса Country:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16

      
    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();
      

    Для того, чтобы показать данные по странам конечным пользователям, необходимо создать новый action. В данном случае вместо размещения нового action'a в контроллере site, будет иметь больше смысла создать новый контроллер - специально для всех действий, относящихся к данным по странам.

    Создние Action

    Создадим новый контроллер CountryController, и action index внутри него.

    controllers/CountryController.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <?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,
          // ]);
          // упростим передачу массива в вид, используя функцию compact()
          
    return $this->render('index'compact('countries','pagination'));
        }
      }

      

    Action index вызывает Country::find(). Данный метод Active Record строит запрос к БД и извлекает все данные из таблицы country. Чтобы ограничить количество стран, возвращаемых каждым запросом, запрос разбивается на страницы с помощью объекта yii\data\Pagination. Объект Pagination служит двум целям:

    1. Устанавливает пункты offset и limit для SQL инструкции, представленной запросом, чтобы она возвращала только одну страницу данных за раз (в нашем случае максимум 5 строк на страницу);
    2. Используется во view для отображения пагинатора, состоящего из набора кнопок с номерами страниц, это будет разъяснено в следующем подразделе.

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

    Создаём View

    Первым делом необходимо создать поддиректорию с именем контроллера (в данном случае имя контроллера CountryController - стало быть поддиректорию следует назвать country) внутри директории views. Эта папка будет использоваться для хранения всех view, выводимых контроллером country. Затем внутри директории views/country создадим файл с именем index.php, содержащий следующий код:

    views/country/index.php:
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?php
      
    use yii\helpers\Html;
      use 
    yii\widgets\LinkPager;

      
    $res="<h1>Страны</h1><ol>";
      foreach(
    $countries as $country){
        
    $res.="<li>Код страны: ".
          
    Html::encode("{$country->code} ({$country->name})") .
          
    "; население: ".
          
    $country->population .
          
    ";</li>";
      }
      
    $res.="</ol>";
      
    $res.=LinkPager::widget(compact('pagination'));

      echo 
    $res;
      unset(
    $res);
      

    Проверка

    Чтобы увидеть, как работает весь вышеприведённый код, перейдите по следующей ссылке в своём браузере: /index.php?r=country%2Findex.

    Рис. 2 Отображение данных по странам, полученных из таблицы countries базы данных
    Рис. 2 Отображение данных по странам, полученных из таблицы countries базы данных

    За кадром Pagination предоставляет всю необходимую функциональность для постраничной разбивки набора данных:

    1. В начале Pagination показывает первую страницу, которая отражает SELECT запрос стран с параметрами LIMIT 5 OFFSET 0. Как результат, первые пять стран будут получены и отображены;
    2. Виджет LinkPager выводит кнопки страниц используя URL'ы, созданные Pagination. Эти URL'ы будут содержать параметр запроса page, который представляет различные номера страниц;
    3. Если вы кликните по кнопке '2', сработает и обработается новый запрос для маршрута country/index. Таким образом новый запрос стран будет иметь параметры LIMIT 5 OFFSET 5 и вернет следующие пять стран для отображения.