Магазин на Yii2, часть 27. Админка: приводим в порядок сгенерированный код
02.09.2019
Теги: CRUD • Web-разработка • Yii2 • ИнтернетМагазин • КаталогТоваров • ПанельУправления • Практика • Фреймворк
Создадим с помощью генератора кода классы модели, контроллера (для CRUD-операций) и файлы view-шаблонов для брендов. Все по аналогии с категориями и товарами каталога. Подробно на этом останавливаться не будем, потому что проделывали это уже несколько раз. И после этого займемся приведением в порядок кода, который сформировал для нас Gii.
Это будет не окончательный вариант, а только первое приближение. Дальше нужно будет еще организовать загрузку файлов изображений для товаров, категорий и брендов; создать выпадающий список для выбора родителя для категории и товара и т.д. и т.п.
Работа с брендами
<?php namespace app\modules\admin\models; use Yii; use yii\db\ActiveRecord; /** * Это модель для таблицы БД `category` * * @property int $id Уникальный идентификатор * @property string $name Наименование бренда * @property string $content Описание бренда * @property string $keywords Мета-тег keywords * @property string $description Мета-тег description * @property string $image Имя файла изображения */ class Brand extends ActiveRecord { /** * Возвращает имя таблицы базы данных */ public static function tableName() { return 'brand'; } /** * Правила валидации полей формы при создании и редактировании бренда */ public function rules() { return [ [['name'], 'required'], [['name', 'content', 'keywords', 'description', 'image'], 'string', 'max' => 255], ]; } /** * Возвращает имена полей формы для создания и редактирования бренда */ public function attributeLabels() { return [ 'id' => 'ID', 'name' => 'Наименование', 'content' => 'Описание', 'keywords' => 'Мета-тег keywords', 'description' => 'Мета-тег description', 'image' => 'Изображение', ]; } }
<?php namespace app\modules\admin\controllers; use Yii; use app\modules\admin\models\Brand; use yii\data\ActiveDataProvider; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; /** * Класс BrandController реализует CRUD для брендов */ class BrandController extends AdminController { public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], ], ]; } /** * Список всех брендов с постраничной навигацией */ public function actionIndex() { $dataProvider = new ActiveDataProvider([ 'query' => Brand::find(), ]); return $this->render('index', [ 'dataProvider' => $dataProvider, ]); } /** * Просмотр данных существующего бренда */ public function actionView($id) { return $this->render('view', [ 'model' => $this->findModel($id), ]); } /** * Создание нового бренда */ public function actionCreate() { $model = new Brand(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('create', [ 'model' => $model, ]); } /** * Обновление существующего бренда */ public function actionUpdate($id) { $model = $this->findModel($id); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('update', [ 'model' => $model, ]); } /** * Удаление существующего бренда */ public function actionDelete($id) { $this->findModel($id)->delete(); return $this->redirect(['index']); } /** * Поиск бренда по идентификатору */ protected function findModel($id) { if (($model = Brand::findOne($id)) !== null) { return $model; } throw new NotFoundHttpException('The requested page does not exist.'); } }
<?php /* * Страница списка всех брендов, файл modules/admin/views/brand/index.php */ use yii\helpers\Html; use yii\grid\GridView; /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Бренды'; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Добавить бренд', ['create'], ['class' => 'btn btn-success']); ?> </p> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'name', [ 'attribute' => 'keywords', 'value' => function($data) { return empty($data->keywords) ? 'Не задано' : $data->keywords; } ], [ 'attribute' => 'description', 'value' => function($data) { return empty($data->description) ? 'Не задано' : $data->description; } ], ['class' => 'yii\grid\ActionColumn'], ], ]); ?>
<?php /* * Страница добавления нового бренда, файл modules/admin/views/brand/create.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Brand */ $this->title = 'Новый бренд'; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', ['model' => $model] ); ?>
<?php /* * Страница редактирования существующего бренда, файл modules/admin/views/brand/update.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Brand */ $this->title = 'Редактирование бренда: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', [ 'model' => $model, ]); ?>
<?php /* * Страница просмотра данных бренда, файл modules/admin/views/brand/view.php */ use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Brand */ $this->title = 'Просмотр бренда: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Изменить', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']); ?> <?= Html::a( 'Удалить', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => 'Вы уверены, что хотите удалить бренд?', 'method' => 'post', ], ] ); ?> </p> <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'name', 'content', 'keywords', 'description', 'image', ], ]); ?>
<?php /* * Форма для добавления и редактирования бренда, файл modules/admin/views/brand/_form.php */ use yii\helpers\Html; use yii\widgets\ActiveForm; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Brand */ /* @var $form yii\widgets\ActiveForm */ ?> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> <?= $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 namespace app\modules\admin\models; use Yii; use yii\db\ActiveRecord; /** * Это модель для таблицы БД `category` * * @property int $id Уникальный идентификатор * @property int $parent_id Родительская категория * @property string $name Наименование категории * @property string $content Описание категории * @property string $keywords Мета-тег keywords * @property string $description Мета-тег description * @property string $image Имя файла изображения */ class Category extends ActiveRecord { /** * Возвращает имя таблицы базы данных */ public static function tableName() { return 'category'; } /** * Возвращает данные о родительской категории */ public function getParent() { return $this->hasOne(Category::class, ['id' => 'parent_id']); } /** * Возвращает наименование родительской категории */ public function getParentName() { $parent = $this->parent; return $parent ? $parent->name : ''; } /** * Правила валидации полей формы при создании и редактировании категории */ public function rules() { return [ [['parent_id'], 'integer'], [['name'], 'required'], [['name', 'content', 'keywords', 'description', 'image'], 'string', 'max' => 255], ]; } /** * Возвращает имена полей формы для создания и редактирования категории */ public function attributeLabels() { return [ 'id' => 'ID', 'parent_id' => 'Родитель', 'name' => 'Наименование', 'content' => 'Описание', 'keywords' => 'Мета-тег keywords', 'description' => 'Мета-тег description', 'image' => 'Изображение' ]; } }
<?php namespace app\modules\admin\controllers; 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 behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], ], ]; } /** * Список всех категорий с постраничной навигацией */ public function actionIndex() { $dataProvider = new ActiveDataProvider([ 'query' => Category::find(), ]); return $this->render('index', [ 'dataProvider' => $dataProvider, ]); } /** * Просмотр данных существующей категории */ public function actionView($id) { return $this->render('view', [ 'model' => $this->findModel($id), ]); } /** * Создание новой категории */ public function actionCreate() { $model = new Category(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('create', [ 'model' => $model, ]); } /** * Обновление существующей категории */ public function actionUpdate($id) { $model = $this->findModel($id); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('update', [ 'model' => $model, ]); } /** * Удаление существующей категории */ public function actionDelete($id) { $this->findModel($id)->delete(); return $this->redirect(['index']); } /** * Поиск категории по идентификатору */ protected function findModel($id) { if (($model = Category::findOne($id)) !== null) { return $model; } throw new NotFoundHttpException('The requested page does not exist.'); } }
<?php /* * Страница списка всех категорий, файл modules/admin/views/category/index.php */ use yii\helpers\Html; use yii\grid\GridView; /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Категории каталога'; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Добавить категорию', ['create'], ['class' => 'btn btn-success']); ?> </p> <?= GridView::widget([ 'dataProvider' => $dataProvider, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], 'name', [ 'attribute' => 'parent_id', 'value' => function($data) { return $data->getParentName(); } ], [ 'attribute' => 'keywords', 'value' => function($data) { return empty($data->keywords) ? 'Не задано' : $data->keywords; } ], [ 'attribute' => 'description', 'value' => function($data) { return empty($data->description) ? 'Не задано' : $data->description; } ], ['class' => 'yii\grid\ActionColumn'], ], ]); ?>
<?php /* * Страница добавления новой категории, файл modules/admin/views/category/create.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Category */ $this->title = 'Новая категория'; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', ['model' => $model] ); ?>
<?php /* * Страница редактирования категории, файл modules/admin/views/category/update.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Category */ $this->title = 'Редактирование категории: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', [ 'model' => $model, ]); ?>
<?php /* * Страница просмотра категории, файл modules/admin/views/category/view.php */ use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Category */ $this->title = 'Просмотр категории: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Изменить', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']); ?> <?= Html::a( 'Удалить', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => 'Вы уверены, что хотите удалить категорию?', 'method' => 'post', ], ] ); ?> </p> <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'name', [ 'attribute' => 'parent_id', 'value' => $model->getParentName() ], 'content', 'keywords', 'description', 'image', ], ]); ?>
<?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, 'parent_id')->textInput() ?> <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> <?= $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 namespace app\modules\admin\models; use Yii; use yii\db\ActiveRecord; /** * Это модель для таблицы БД `product` * * @property int $id Уникальный идентификатор * @property int $category_id Родительская категория * @property int $brand_id Идентификатор бренда * @property string $name Наименование товара * @property string $content Описание товара * @property string $price Цена товара * @property string $keywords Мета-тег keywords * @property string $description Мета-тег description * @property string $image Имя файла изображения * @property int $hit Лидер продаж? * @property int $new Новый товар? * @property int $sale Распродажа? */ class Product extends ActiveRecord { /** * Возвращает имя таблицы базы данных */ public static function tableName() { return 'product'; } /** * Возвращает данные о родительской категории */ public function getCategory() { return $this->hasOne(Category::class, ['id' => 'category_id']); } /** * Возвращает наименование родительской категории */ public function getCategoryName() { $parent = $this->category; return $parent ? $parent->name : ''; } /** * Возвращает данные о бренде товара */ public function getBrand() { return $this->hasOne(Brand::class, ['id' => 'brand_id']); } /** * Возвращает наименование бренда товара */ public function getBrandName() { $brand = $this->brand; return $brand ? $brand->name : ''; } /** * Правила валидации полей формы при создании и редактировании товара */ public function rules() { return [ [['category_id', 'brand_id', 'name'], 'required'], [['category_id', 'brand_id', 'hit', 'new', 'sale'], 'integer'], [['content'], 'string'], [['price'], 'number'], [['name', 'keywords', 'description', 'image'], 'string', 'max' => 255], ]; } /** * Возвращает имена полей формы для создания и редактирования товара */ public function attributeLabels() { return [ 'id' => 'ID', 'category_id' => 'Категория', 'brand_id' => 'Бренд', 'name' => 'Наименование', 'content' => 'Описание', 'price' => 'Цена', 'keywords' => 'Мета-тег keywords', 'description' => 'Мета-тег description', 'image' => 'Изображение', 'hit' => 'Лидер продаж', 'new' => 'Новинка', 'sale' => 'Распродажа', ]; } }
<?php namespace app\modules\admin\controllers; use Yii; use app\modules\admin\models\Product; use yii\data\ActiveDataProvider; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; /** * Класс ProductController реализует CRUD для товаров */ class ProductController extends AdminController { public function behaviors() { return [ 'verbs' => [ 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['POST'], ], ], ]; } /** * Список всех товаров с постраничной навигацией */ public function actionIndex() { $dataProvider = new ActiveDataProvider([ 'query' => Product::find(), ]); return $this->render('index', [ 'dataProvider' => $dataProvider, ]); } /** * Просмотр данных существующего товара */ public function actionView($id) { return $this->render('view', [ 'model' => $this->findModel($id), ]); } /** * Создание нового товара */ public function actionCreate() { $model = new Product(); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('create', [ 'model' => $model, ]); } /** * Обновление существующего товара */ public function actionUpdate($id) { $model = $this->findModel($id); if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); } return $this->render('update', [ 'model' => $model, ]); } /** * Удаление существующего товара */ public function actionDelete($id) { $this->findModel($id)->delete(); return $this->redirect(['index']); } /** * Поиск товара по идентификатору */ protected function findModel($id) { if (($model = Product::findOne($id)) !== null) { return $model; } throw new NotFoundHttpException('The requested page does not exist.'); } }
<?php /* * Страница списка всех товаров, файл modules/admin/views/product/index.php */ use yii\helpers\Html; use yii\grid\GridView; /* @var $this yii\web\View */ /* @var $dataProvider yii\data\ActiveDataProvider */ $this->title = 'Товары каталога'; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Добавить товар', ['create'], ['class' => 'btn btn-success']); ?> </p> <?= GridView::widget([ 'dataProvider' => $dataProvider, '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'], ], ]); ?>
<?php /* * Страница добавления нового товара, файл modules/admin/views/product/create.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Product */ $this->title = 'Новый товар'; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', ['model' => $model] ); ?>
<?php /* * Страница редактирования товара, файл modules/admin/views/product/update.php */ use yii\helpers\Html; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Product */ $this->title = 'Редактирование товара: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <?= $this->render( '_form', ['model' => $model] ); ?>
<?php /* * Страница просмотра товара, файл modules/admin/views/product/view.php */ use yii\helpers\Html; use yii\widgets\DetailView; /* @var $this yii\web\View */ /* @var $model app\modules\admin\models\Product */ $this->title = 'Просмотр товара: ' . $model->name; ?> <h1><?= Html::encode($this->title); ?></h1> <p> <?= Html::a('Изменить', ['update', 'id' => $model->id], ['class' => 'btn btn-primary']); ?> <?= Html::a( 'Удалить', ['delete', 'id' => $model->id], [ 'class' => 'btn btn-danger', 'data' => [ 'confirm' => 'Вы уверены, что хотите удалить товар?', 'method' => 'post', ], ] ); ?> </p> <?= DetailView::widget([ 'model' => $model, 'attributes' => [ 'name', [ 'attribute' => 'category_id', 'value' => $model->getCategoryName() ], [ 'attribute' => 'brand_id', 'value' => $model->getBrandName() ], 'price', 'content:html', 'keywords', 'description', 'image', [ 'attribute' => 'hit', 'value' => $model->hit ? 'Да' : 'Нет' ], [ 'attribute' => 'new', 'value' => $model->new ? 'Да' : 'Нет' ], [ 'attribute' => 'sale', 'value' => $model->sale ? 'Да' : 'Нет' ], ], ]); ?>
<?php /* * Форма для добавления и редактирования товара, файл modules/admin/views/product/_form.php */ 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')->textInput(); ?> <?= $form->field($model, 'brand_id')->textInput(); ?> <?= $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(); ?>
- Магазин на Yii2, часть 33. Админка: приводим в порядок CRUD-код для страниц
- Магазин на Yii2, часть 32. Админка: удаление категорий и CRUD для страниц
- Магазин на Yii2, часть 31. Админка: загрузка изображений для категорий и брендов
- Магазин на Yii2, часть 30. Админка: WYSIWYG-редактор и изображение для товара
- Магазин на Yii2, часть 29. Админка: добавляем список товаров категории
- Магазин на Yii2, часть 28. Админка: выбор родителя и список всех категорий
- Магазин на Yii2, часть 26. Админка: модели и контроллеры для категорий и товаров
Поиск: Web-разработка • Yii2 • Интернет магазин • Каталог товаров • Панель управления • Фреймворк • Gii • CRUD