Магазин на Yii2, часть 29. Админка: добавляем список товаров категории

10.09.2019

Теги: CRUDWeb-разработкаYii2ИнтернетМагазинКаталогТоваровПанельУправленияПрактикаФреймворк

Сейчас для действия index контроллера ProductController показывается список всех товаров каталога. Найти в этом длинном списке нужный товар, чтобы его отредактировать, довольно проблематично. Давайте на страницу списка всех категорий добавим еще одну ссылку, которая позволит просмотреть список товаров каждой категории. Для этого добавим метод actionProducts() для контроллера CategoryController:

<?php
namespace app\modules\admin\controllers;

use app\modules\admin\models\Product;
use Yii;
use app\modules\admin\models\Category;
use yii\data\ActiveDataProvider;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * Класс CategoryController реализует CRUD для категорий
 */
class CategoryController extends AdminController {

    /*...*/

    /**
     * Список всех товаров категории
     */
    public function actionProducts($id) {
        // получаем массив идентификаторов всех потомков категории,
        // чтобы запросом выбрать товары и в дочерних категориях
        $ids = Category::getAllChildIds($id);
        $ids[] = $id;
        $products = new ActiveDataProvider([
            'query' => Product::find()->where(['in', 'category_id', $ids])
        ]);
        return $this->render(
            'products',
            [
                'category' => $this->findModel($id),
                'products' => $products,
            ]
        );
    }

    /*...*/
}

Теперь добавим ссылку для просмотра товаров категории в view-шаблон:

<?php
/*
 * Страница списка всех категорий, файл modules/admin/views/category/index.php
 */
use yii\helpers\Html;

/* @var $this yii\web\View */

$this->title = 'Категории каталога';
?>

<h1><?= Html::encode($this->title); ?></h1>
<p>
    <?= Html::a('Добавить категорию', ['create'], ['class' => 'btn btn-success']); ?>
</p>

<table class="table table-striped table-bordered">
    <thead>
        <tr>
            <th>Наименование</th>
            <th>Мета-тег keywords</th>
            <th>Мета-тег description</th>
            <th><span class="glyphicon glyphicon-list"></span></th>
            <th><span class="glyphicon glyphicon-eye-open"></span></th>
            <th><span class="glyphicon glyphicon-pencil"></span></th>
            <th><span class="glyphicon glyphicon-trash"></span></th>
        </tr>
    </thead>
    <tbody>
    <?php foreach ($categories as $category): ?>
        <tr>
            <td><?= $category['name']; ?></td>
            <td><?= $category['keywords']; ?></td>
            <td><?= $category['description']; ?></td>
            <td>
                <?php
                echo Html::a(
                    '<span class="glyphicon glyphicon-list"></span>',
                    ['/admin/category/products', 'id' => $category['id']]
                );
                ?>
            </td>
            <td>
                ..........
            </td>
            <td>
                ..........
            </td>
            <td>
                ..........
            </td>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>

Создадим новый view-шаблон для списка товаров категории:

<?php
/*
 * Страница списка товаров категории, файл modules/admin/views/category/products.php
 */
use yii\helpers\Url;
use yii\helpers\Html;
use yii\grid\GridView;

/* @var $this yii\web\View */
/* @var $category app\modules\admin\models\Category  */
/* @var $products yii\data\ActiveDataProvider */

$this->title = 'Товары категории: ' . $category->name;
?>

<h1><?= Html::encode($this->title) ?></h1>
<p>
    <?=
    Html::a(
        'Добавить товар',
        ['/admin/product/create', 'category' => $category->id],
        ['class' => 'btn btn-success']
    );
    ?>
</p>

<?=
GridView::widget([
    'dataProvider' => $products,
    'columns' => [
        ['class' => 'yii\grid\SerialColumn'],
        'name',
        [
            'attribute' => 'category_id',
            'value' => function($data){
                return $data->getCategoryName();
            }
        ],
        [
            'attribute' => 'brand_id',
            'value' => function($data){
                return $data->getBrandName();
            }
        ],
        'price',
        [
            'attribute' => 'hit',
            'value' => function($data) {
                return $data->hit ? 'Да' : 'Нет';
            }
        ],
        [
            'attribute' => 'new',
            'value' => function($data) {
                return $data->new ? 'Да' : 'Нет';
            }
        ],
        [
            'attribute' => 'sale',
            'value' => function($data) {
                return $data->sale ? 'Да' : 'Нет';
            }
        ],
        [
            'class' => 'yii\grid\ActionColumn',
            'urlCreator' => function ($action, $model, $key, $index) {
                return Url::to(['/admin/product/'.$action, 'id' => $model->id]);
            }
        ],
    ],
]);
?>

И нам еще потребуется метод в модели Category, который позволит получить идентификаторы всех потомков категории:

<?php
namespace app\modules\admin\models;

use yii\db\ActiveRecord;

/**
 * Это модель для таблицы БД `category`
 */
class Category extends ActiveRecord {

    /*...*/

    /**
     * Возвращает массив идентификаторов всех потомков категории $id,
     * т.е. дочерние, дочерние дочерних и так далее
     */
    public static function getAllChildIds($id) {
        $children = [];
        $ids = self::getChildIds($id);
        foreach ($ids as $item) {
            $children[] = $item;
            $c = self::getAllChildIds($item);
            foreach ($c as $v) {
                $children[] = $v;
            }
        }
        return $children;
    }

    /**
     * Возвращает массив идентификаторов дочерних категорий (прямых
     * потомков) категории с уникальным идентификатором $id
     */
    protected static function getChildIds($id) {
        $children = self::find()->where(['parent_id' => $id])->asArray()->all();
        $ids = [];
        foreach ($children as $child) {
            $ids[] = $child['id'];
        }
        return $ids;
    }
    
    /*...*/
}

Обратите внимание, что ссылка на добавление товара в шаблоне products.php имеет вид:

<p>
    <?=
    Html::a(
        'Добавить товар',
        ['/admin/product/create', 'category' => $category->id],
        ['class' => 'btn btn-success']
    );
    ?>
</p>

Это для того, чтобы в выпадающем списке выбора родителя сразу установить нужное значение. Вот как это работает:

<?php
/*
 * Форма для добавления и редактирования товара, файл modules/admin/views/product/_form.php
 */

use app\modules\admin\models\Brand;
use app\modules\admin\models\Category;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $this yii\web\View */
/* @var $model app\modules\admin\models\Product */
/* @var $form yii\widgets\ActiveForm */
?>

<?php $form = ActiveForm::begin(); ?>
    <?= $form->field($model, 'name')->textInput(['maxlength' => true]); ?>
    <?php
    $category = Yii::$app->request->get('category') ?: 0;
    $param = ['options' => [$category => ['selected' => true]]];
    echo $form->field($model, 'category_id')->dropDownList(Category::getTree(), $param);
    ?>
    <?=
    $form->field($model, 'brand_id')->dropDownList(
        ArrayHelper::map(Brand::find()->all(), 'id', 'name')
    );
    ?>
    <?= $form->field($model, 'price')->textInput(['maxlength' => true]); ?>
    <?= $form->field($model, 'image')->textInput(['maxlength' => true]); ?>
    <?= $form->field($model, 'content')->textarea(['rows' => 6]); ?>
    <?= $form->field($model, 'keywords')->textarea(['rows' => 2, 'maxlength' => true]); ?>
    <?= $form->field($model, 'description')->textarea(['rows' => 2, 'maxlength' => true]); ?>
    <?= $form->field($model, 'hit')->textInput(); ?>
    <?= $form->field($model, 'new')->textInput(); ?>
    <?= $form->field($model, 'sale')->textInput(); ?>
    <div class="form-group">
        <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?>
    </div>
<?php ActiveForm::end(); ?>

Поиск: Web-разработка • Yii2 • Интернет магазин • Каталог товаров • Панель управления • Фреймворк • Практика • CRUD

Каталог оборудования
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.