Магазин на Yii2, часть 28. Админка: выбор родителя и список всех категорий
08.09.2019
Теги: CRUD • Web-разработка • Yii2 • Иерархия • ИнтернетМагазин • КаталогТоваров • ПанельУправления • Практика • Список • Фреймворк
Продолжим работу по приведению в порядок кода, который для нас сформировал Gii. В первую очередь займемся созданием выпадающего списка для выбора родителя при создании и редактировании категории или товара. Для этого добавим в класс модели Category
два метода, которые будут возвращать список всех категорий в упорядоченном виде:
<?php namespace app\modules\admin\models; use Yii; use yii\db\ActiveRecord; class Category extends ActiveRecord { /*...*/ /** * Возвращает массив всех категорий каталога в виде дерева */ public static function getAllCategories($parent = 0, $level = 0, $exclude = 0) { $children = self::find() ->where(['parent_id' => $parent]) ->asArray() ->all(); $result = []; foreach ($children as $category) { // при выборе родителя категории нельзя допустить // чтобы она размещалась внутри самой себя if ($category['id'] == $exclude) { continue; } if ($level) { $category['name'] = str_repeat('— ', $level) . $category['name']; } $result[] = $category; $result = array_merge( $result, self::getAllCategories($category['id'], $level+1, $exclude) ); } return $result; } /** * Возвращает массив всех категорий каталога для возможности * выбора родителя при добавлении или редактировании товара * или категории */ public static function getTree($exclude = 0, $root = false) { $data = self::getAllCategories(0, 0, $exclude); $tree = []; // при выборе родителя категории можно выбрать значение «Без родителя», // т.е. создать категорию верхнего уровня, у которой не будет родителя if ($root) { $tree[0] = 'Без родителя'; } foreach ($data as $item) { $tree[$item['id']] = $item['name']; } return $tree; } }
Выбор родителя для категории и товара
Теперь изменим форму добавления или редактирования категории — заменим input
на select
:
<?php /* * Форма для добавления и редактирования категории, файл modules/admin/views/category/_form.php */ use yii\helpers\Html; use yii\widgets\ActiveForm; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Category */ /* @var $form yii\widgets\ActiveForm */ ?> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'name')->textInput(['maxlength' => true]); ?> <?php // при редактировании существующей категории нельзя допустить, чтобы // в качестве родителя была выбрана эта же категория или ее потомок $exclude = 0; if (!empty($model->id)) { $exclude = $model->id; } $parents = $model::getTree($exclude, true); echo $form->field($model, 'parent_id')->dropDownList($parents); ?> <?= $form->field($model, 'content')->textarea(['rows' => 2, 'maxlength' => true]); ?> <?= $form->field($model, 'keywords')->textarea(['rows' => 2, 'maxlength' => true]); ?> <?= $form->field($model, 'description')->textarea(['rows' => 2, 'maxlength' => true]); ?> <?= $form->field($model, 'image')->textInput(['maxlength' => true]) ?> <div class="form-group"> <?= Html::submitButton('Сохранить', ['class' => 'btn btn-success']) ?> </div> <?php ActiveForm::end(); ?>
И вот что у нас получилось в итоге:
Аналогично, изменим форму для добавления и редактирования товара:
<?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]); ?> <?= $form->field($model, 'category_id')->dropDownList(Category::getTree()); ?> <?= $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(); ?>
Список всех категорий
Сейчас список всех категорий показывается с использованием провайдера данных ActiveDataProvider
и виджета GridView
. Нам это не подходит, потому что категории должны показываться с учетом вложенности. Так что изменим метод контроллера actionIndex()
и view-шаблон index.php
:
<?php namespace app\modules\admin\controllers; use Yii; use app\modules\admin\models\Category; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; /** * Класс OrderController реализует CRUD для категорий */ class CategoryController extends AdminController { /*...*/ /** * Список всех категорий каталога товаров */ public function actionIndex() { return $this->render( 'index', ['categories' => Category::getAllCategories()] ); } /*...*/ }
<?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-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> <?= Html::a( '<span class="glyphicon glyphicon-eye-open"></span>', ['/admin/category/view', 'id' => $category['id']] ); ?> </td> <td> <?= Html::a( '<span class="glyphicon glyphicon-pencil"></span>', ['/admin/category/update', 'id' => $category['id']] ); ?> </td> <td> <?= Html::a( '<span class="glyphicon glyphicon-trash"></span>', ['/admin/category/delete', 'id' => $category['id']], [ 'data-confirm' => 'Вы уверены, что хотите удалить эту категорию?', 'data-method' => 'post' ] ); ?> </td> </tr> <?php endforeach; ?> </tbody> </table>
- Магазин на Yii2, часть 33. Админка: приводим в порядок CRUD-код для страниц
- Магазин на Yii2, часть 32. Админка: удаление категорий и CRUD для страниц
- Магазин на Yii2, часть 31. Админка: загрузка изображений для категорий и брендов
- Магазин на Yii2, часть 30. Админка: WYSIWYG-редактор и изображение для товара
- Магазин на Yii2, часть 29. Админка: добавляем список товаров категории
- Магазин на Yii2, часть 27. Админка: приводим в порядок сгенерированный код
- Магазин на Yii2, часть 26. Админка: модели и контроллеры для категорий и товаров
Поиск: Web-разработка • Yii2 • Иерархия • Интернет магазин • Каталог товаров • Практика • Список • Фреймворк • CRUD