Yii2. Связанные данные

18.03.2019

Теги: Web-разработкаYii2БазаДанныхТеорияФреймворкШаблонСайта

Помимо работы с отдельными таблицами баз данных, ActiveRecord также имеет возможность объединять связные данные, что делает их доступными для получения через основные объекты данных. Например, раздел каталога связан с товарами, которые в нем размещены. С помощью объявления этой связи можно получить доступ к информации о товарах категории с помощью выражения $category->products.

-- Таблица `category`

CREATE TABLE `category` (
  `id` int(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'Первичный ключ',
  `parent_id` int(10) NOT NULL DEFAULT '0' COMMENT 'Родительская категория',
  `name` varchar(100) NOT NULL COMMENT 'Название категории',
  `sortorder` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Порядок сортировки'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `category` (`id`, `parent_id`, `name`, `sortorder`) VALUES
(1, 0, 'Первая категория', 1),
(2, 0, 'Вторая категория', 2),
(3, 0, 'Третья категория', 3),
(4, 0, 'Четвертая категрия', 4),
(5, 1, 'Дочерняя категория', 1);

-- Таблица `product`

CREATE TABLE `product` (
  `id` int(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'Первичный ключ',
  `category_id` int(10) NOT NULL DEFAULT '0' COMMENT 'Родительская категория',
  `name` varchar(200) NOT NULL COMMENT 'Название товара',
  `sortorder` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Порядок сортировки'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `product` (`id`, `category_id`, `name`, `sortorder`) VALUES
(1, 1, 'Первый товар', 1),
(2, 1, 'Второй товар', 2),
(3, 2, 'Первый товар', 1),
(4, 2, 'Второй товар', 2),
(5, 5, 'Пятый товар', 1),
(6, 5, 'Шестой товар', 2);

Объявляем связи в кассах моделей Category и Product:

<?php
/*
 * Файл models/Category.php
 */
namespace app\models;
use yii\db\ActiveRecord;

class Category extends ActiveRecord {
    public function getProducts() {
        // связь таблицы БД `category` с таблицей `product`
        return $this->hasMany(Product::className(), ['category_id' => 'id']);
    }

    public function getParent() {
        // связь таблицы БД `category` с таблицей `category`
        return $this->hasOne(self::className(), ['id' => 'parent_id']);
    }
}
<?php
/*
 * Файл models/Product.php
 */
namespace app\models;
use yii\db\ActiveRecord;

class Product extends ActiveRecord {
    public function getCategory() {
        // связь таблицы БД `product` с таблицей `category`
        return $this->hasOne(Category::className(), ['id' => 'category_id']);
    }
}

В контроллере получаем данные о каком-то товаре и о какой-то категории:

<?php

namespace app\controllers;

use yii\web\Controller;
use app\models\Category;
use app\models\Product;

class CatalogController extends Controller {

    public function actionCategory() {
        // получаем информацию о категории с идентификатором 5
        $category = Category::findOne(5);
        return $this->render('category', ['category' => $category]);
    }

    public function actionProduct() {
        // получаем информацию о товаре с идентификатором 2
        $product = Product::findOne(2);
        return $this->render('product', ['product' => $product]);
    }
}

Теперь в view-шаблоне views/catalog/category.php мы можем получить не только информацию о категории:

<?php
use yii\helpers\Html;
?>
<div class="catalog-category">
    <h1><?= Html::encode($category->name); ?></h1>
</div>
SELECT * FROM `category` WHERE `id` = 5

Но и получить информацию о товарах категории и данные о родительской категории:

<?php
use yii\helpers\Html;
?>
<div class="catalog-category">
    <h1><?= Html::encode($category->name); ?></h1>

    <?php $products = $category->products; /* товары категории */ ?>
    <?php if (!empty($products)): ?>
        <ul>
        <?php foreach ($products as $product): ?>
            <li><?= Html::encode($product->name); ?></li>
        <?php endforeach; ?>
        </ul>
    <?php else: ?>
        <p>Нет товаров в этой категории</p>
    <?php endif; ?>

    <?php $parent = $category->parent; /* родительская категория */ ?>
    <?php if (!empty($parent)): ?>
        <p>Родительская категория: <?= Html::encode($parent->name); ?></p>
    <?php endif; ?>
</div>
SELECT * FROM `category` WHERE `id` = 5
-- дополнительный запрос после $products = $category->products;
SELECT * FROM `product` WHERE `category_id` = 5
-- дополнительный запрос после $parent = $category->parent;
SELECT * FROM `category` WHERE `id` = 1

Аналогично, в view-шаблоне views/catalog/product.php можем получить не только информацию о товаре:

<?php
use yii\helpers\Html;
?>
<div class="catalog-product">
    <h1><?= Html::encode($product->name); ?></h1>
</div>
SELECT * FROM `product` WHERE `id` = 2

Но и получить информацию о родительской категории товара. А потом получить информацию о других товарах в родительской категории:

<?php
use yii\helpers\Html;
?>
<div class="catalog-product">
    <h1><?= Html::encode($product->name); ?></h1>
    <?php $category = $product->category; /* родительская категория */ ?>
    <?php if (!empty($category)): ?>
        <p>Родительская категория: <?= Html::encode($category->name); ?></p>
        <?php $products = $category->products; /* другие товары в родительской категории */ ?>
        <?php if (!empty($products)): ?>
            <ul>
            <?php foreach ($products as $item): ?>
                <li><?= Html::encode($item->name); ?></li>
            <?php endforeach; ?>
            </ul>
        <?php endif; ?>   
    <?php endif; ?>
</div>
SELECT * FROM `product` WHERE `id` = 2
-- дополнительный запрос после $category = $product->category;
SELECT * FROM `category` WHERE `id` = 1
-- дополнительный запрос после $products = $category->products;
SELECT * FROM `product` WHERE `category_id` = 1

Поиск: Web-разработка • Yii2 • База данных • Фреймворк • Шаблон сайта • Связанные данные • Модель • Model • hasOne • HasMany

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.