Сегодня мы займёмся панелью управления сайта. Часть этой панели мы уже сделали.
В третьей части (Аутентификация) мы создали контроллер DashboardController
и переместили в него методы actionLogin
и actionLogout
.
Теперь нам нужно добавить методы для управления играми, пользователями и жанрами. По большому счёту, нужные методы у нас есть, они были автоматически созданы утилитой yiic, но часть методов нужно переделывать. Например, методы управления жанрами нам вполне подходят, т.к. ничего кроме обычных CRUD операций с жанрами нам делать не нужно. Но при редактировании игр нам нужны дополнительные возможности.
Для каждой игры нужно показать полный перечень жанров с чекбоксами, чтобы пользователь мог его отредактировать. Кроме того, нужен список скриншотов, и возможность удаления неподходящих.
В первую очередь создадим отдельный макет для страниц админки.
Создаём файл (protected/views/layouts/dashboard.php
). Я покажу только несколько его фрагментов
<!DOCTYPE html ...> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> ... <title><?php echo $this->pageTitle; ?></title> </head> <body> <div id="page" class="container_12"> <div id="header" class="grid_12"> <div id="logo">Панель управления</div> </div><!-- header --> <div id="sidebar" class="grid_4"> <?php $this->widget('application.components.dashboardMenu'); ?> </div><!-- sidebar --> <div class="grid_8"> <div id="content"> <?php echo $content; ?> <div class="clear"></div> </div><!-- content --> </div> <div id="footer" class="grid_12"> ... </div><!-- footer --> <div class="clear"></div> </div><!-- page --> </body> </html>
Как видите, шаблон стандартный: шапка, меню слева, блок контента и хвостовик.
Обратите внимание на сайдбар. Он создан с помощью виджета application.components.dashboardMenu
. Подробно создание виджетов мы рассматривали в восьмой части.
Этот виджет просто выводит список ссылок на основные страницы панели управления. Единственная особенность в том, что мы не показываем его на странице с формой входа. Для этого в методе run
выполняется соответствующая проверка.
public function run() { //если мы находимся на странице с формой входа, то этот виджет не показываем $action = Yii::app()->controller->action->id; if ('login' === $action) { return; } $this->render('dashboardMenu'); }
Переходим к более сложной части – управлению играми.
В меню для игр предусмотрено два пункта: Управление (вызывается метод actionAdmin
контроллера GamesController
) и Импорт (метод actionImport
контроллера GamesController
).
Обратите внимание, у нас нет пункта «Создать игру». Дело в том, что все игры мы получаем из фида партнёрки. Т.е. за создание новых игр отвечает метод «Импорт» (его мы рассматривали в пятой части).
Метод actionAdmin
выводит таблицу с общим перечнем игр и ссылками на действия Update и Delete. Сам метод создан утилитой yiic и мои изменения коснулись только количества столбцов в результирующей таблице. По-умолчанию, выводятся все поля, но от большинства из них в этой таблице нет никакой практической пользы.
Теперь рассмотрим каким образом выполняется изменение игр (метод actionUpdate
).
public function actionUpdate() { $cs = Yii::app()->clientScript; //подключаем редактор tinyMce для всех textarea $cs->registerScriptFile(Yii::app()->request->baseUrl.'/js/tiny_mce/tiny_mce_gzip.js', CClientScript::POS_END); $cs->registerScriptFile(Yii::app()->request->baseUrl.'/js/tiny_mce/init_gz.js' ,CClientScript::POS_END); $cs->registerScriptFile(Yii::app()->request->baseUrl.'/js/tiny_mce/init_editor.js' ,CClientScript::POS_END); //получаем данные игры из базы $model=$this->loadGames(); //получаем список жанров $types = Types::model()->findAll(); //если получены данные игры if(isset($_POST['Games'])) { //записываем атрибуты $model->attributes=$_POST['Games']; //получаем список чекбоксов, соответствующих выбранным жанрам... $model->g_types=$_POST['types']; //... кодируем их и результат записываем в атрибут g_type $model->g_type = $this->_encodeTypes(); //эта переменная запрещает изменение списка скриншотов игры //(т.к. для удаления скриншотов используется отдельная форма) $model->updateScreenshots = false; //сохраняем игру if($model->save()) $this->redirect(array('update','id'=>$model->g_id)); } //если получены данные из формы удаления скриншотов if (isset($_POST['screenshots'])) { //удаляем выбранные скриншоты foreach ($_POST['screenshots'] as $id) { $s = Screenshots::model()->findByPk($id); $s->delete(); } } //показываем форму $this->render('update',array('model'=>$model, 'types'=>$types)); }
В первую очередь, подключаем редактор tinyMce. Для этого используется метод registerScriptFile
и работу с ним мы рассматривали седьмой части, поэтому повторяться не буду.
Затем, получаем данные игры из базы (с помощью метода loadGames
, строка 9).
Кроме того, нам понадобится полный список жанров (строка 11). Мы создадим блок с чекбоксами и дадим пользователю возможность изменять список жанров к которым относится игра. Кроме того, для удаления ненужных скриншотов мы добавим на страницу дополнительную форму.
На следующем этапе проверяем заходит ли пользователь первый раз на страницу или он отправил форму с обновлёнными данными игры.
Сохранение данных выполняется в два этапа:
1) проверяем какие чекбоксы выбраны и кодируем жанр игры (строки 18-20);
2) сохраняем изменённые данные (строки 25, 26), если сохранение прошло успешно, отправляем редирект на эту же страницу.
Обратите внимание, на атрибут updateScreenshots
. Мы установили его значение равным false
. Это означает, что при изменении игры скриншоты удаляться не будут. Проверка этого атрибута выполняется в методе afterSave
модели Games
.
Если пришли данные формы скриншотов, то удаляем выбранные (строки 29-35).
Рассмотрим представление views/games/update.php
.
<?php //страница "Редактирование игры" //шаблон dashboard $this->layout = 'dashboard'; ?> <h2>Редактирование: <?php echo $model->g_name; ?></h2> <div class="actionBar"> [<?php echo CHtml::link('Просмотр',array('list')); ?>] [<?php echo CHtml::link('Управление играми',array('admin')); ?>] </div> <?php echo $this->renderPartial('_form', array( 'model'=>$model, 'update'=>true, 'types'=>$types )); ?>
Обратите внимание, что здесь мы явно указываем какой макет нужно использовать (строка 3). А для создания формы используется представление views/games/_form.php
, которому мы передаём данные выбранной игры и полный список жанров.
Приводить код всего представления _form.php
я не будут, т.к. в нём много повторяющихся блоков. Остановимся на создании блока со списком жанров и формы со скриншотами.
<?php //Эта форма используется для обновления данных игры и удаления скриншотов ?> <div class="yiiForm"> <p> Обязательные поля отмеченны <span class="required">*</span>. </p> <?php echo CHtml::beginForm(); ?> <?php echo CHtml::errorSummary($model); ?> <div class="simple"> <?php echo CHtml::activeLabelEx($model,'g_rate'); ?> <?php echo CHtml::activeTextField($model,'g_rate'); ?> </div> ... <?php echo CHtml::activeLabelEx($model,'g_state'); ?> <?php echo CHtml::activeDropDownList($model, 'g_state' , array('0'=>'Опубликовано','1'=>'Черновик')); ?> </div> <div class="types_list"> <?php echo '<strong>Жанры</strong>:<br />'; ?> <?php $curTypes = $model->ygs_types; $curT = array(); foreach ($curTypes as $type) { $curT[] = $type->t_id; } $allT = array(); foreach ($types as $type) { $allT[$type->t_id] = $type->t_name; } echo CHtml::checkBoxList('types',$curT,$allT, array('separator'=>'')); ?> ... <?php echo CHtml::endForm(); ?> </div><!-- yiiForm --> <?php //форма удаления скриншотов ?> <div class="yiiForm"> <h2>Управление скриншотами</h2> <?php echo CHtml::beginForm('', 'post', array('id'=>'screenshots_form')); ?> <div class="simple"> <?php $screenshots = $model->ygs_screenshots; $gameScreenshots = array(); foreach ($screenshots as $screenshot) { $gameScreenshots[$screenshot->s_id] = CHtml::image($screenshot->s_thumbnail, $screenshot->s_game_id); } echo CHtml::checkBoxList('screenshots',array(),$gameScreenshots); ?> </div> <div class="action"> <?php echo CHtml::submitButton('Удалить отмеченные'); ?> </div> <?php echo CHtml::endForm(); ?> </div><!-- yiiForm -->
Для вывода списка чекбоксов мы использовали метод CHtml::checkBoxList
. Для этого метода нам нужно сформировать два массива: со значениями и с текстом соответствующих чекбоксов. Эти массивы формируются в циклах (строки 28-34).
Форма со списком скриншотов формируется точно также. Мы создаём список чекбоксов и около каждого вставляем картинку (метод CHtml::image
).
Как видите, принцип создания админки достаточно простой. В качестве основы используем код, который создаёт утилита yiic. Если форма нас не устраивает, например, потому что нужны дополнительные поля, просто добавляем их.
На этом мы сегодня остановимся. Приводить код всех представлений, которые используются в админке, я не вижу смысла.
Если есть вопросы или замечания, пишите, обсудим 😉
P.S. Вы можете скачать архив с исходным кодом этого примера
SourceВсе разделы цикла.
- Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.
- Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.
- Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.
- Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.
- Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.
- Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.
- Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.
- Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.
- Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.
- Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.
- Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.
- Архив с исходниками
Интересно почитать