Хочу поделиться небольшим модулем, предназначенным для создания страницы настроек в своём приложении. А заодно узнать у сообщества, что в нём можно было бы улучшить.
Задача по своей идее простая — сделать табличку в БД, хранящую параметры типа «ключ -> значение», а к ней сделать страничку редактирования, позволяющую изменять данные значения. ну и конечно же реализовать программный интерфейс для доступа к параметрам хранимым в БД.
Срок реализации — около получаса. В интернете почему-то готового решения было не найти. Исправим положение, авось кому пригодится.
Делать будем на конкретном примере. Допустим, нам необходимо хранить такие настройки: Имя приложения, Описание приложения, Пароль для Gii, Email администратора.
Пишем
Итак, для начала создадим структуру каталогов, в которой сложим наш модуль:
configpage components Econfig.php conrollers WtsController.php models WtsConfigForm.php views wts config.php configForm.php ConfigpageModule.php
Не будем ничего выдумывать и используем готовое расширения для хранения настроек в БД — EConfig. Его и сложим в каталог components. Данное расширение имеет два метода «get» и «set», а также само умеет создавать таблицу в БД, то есть париться по его настройке не придётся.
Шаблон для нашего модуля сгенерирован через Gii и основной файл модуля ConfigpageModule.php остаётся без изменений:
class ConfigpageModule extends CWebModule { public function init() { $this->setImport(array( 'configpage.models.*', 'configpage.components.*', )); } public function beforeControllerAction($controller, $action) { if(parent::beforeControllerAction($controller, $action)) { return true; } else return false; } }
Куда интереснее обстоят дела с самой формой. Для её создания мы можем воспользоваться конструктором форм, входящим в поставку Yii. Подробнее о нём можно почитать здесь.
Если вкратце, то нам понадобится создать модель формы, контроллер, описание формы и вьюшку. Начнём с модели.
WtsConfigForm.php:
class WtsConfigForm extends CFormModel { public $applicationName; public $applicationShortDesc; public $giiPassword; public $adminEmail; public function rules() { return array( array('applicationName, giiPassword, adminEmail, applicationShortDesc', 'required'), ); } public function attributeLabels() { return array( 'applicationName' => Yii::t('app', 'Наименование приложения'), 'applicationShortDesc' => Yii::t('app', 'Краткое описание приложения'), 'giiPassword' => Yii::t('app', 'Пароль для генератора кода Gii'), 'adminEmail' => Yii::t('app', 'Email администратора'), ); } }
Всё просто — описали 4 поля, описали их метки и указали правило, утверждающее, что поле является обязательным. Хинт: если не указать поле как обязательное, оно не появится на форме.
Окейно. Контроллер оставим на сладкое, а пока опишем форму и вьюшку. Описание формы — это простой массив, в котором хранится описание полей и элементов управления формы.
configForm.php:
return array( 'elements'=>array( 'mainSettings'=>array( 'type'=>'form', 'title'=>'Основные настройки', 'elements'=>array( 'applicationName'=>array('type'=>'text',), 'applicationShortDesc'=>array('type'=>'text',), ), ), 'systemSettings'=>array( 'type'=>'form', 'title'=>'Системные настройки', 'elements'=>array( 'adminEmail'=>array('type'=>'text',), 'giiPassword'=>array('type'=>'text', ), ), ), ), 'buttons'=>array( 'configPage'=>array( 'type'=>'submit', 'label'=>'Сохранить', ), ), );
Просто? Вот и я думаю что да. Мы выделили две группы настроек — основные и системные, в каждой группе описали некие поля, присутствующие в модели и снизу расположили кнопку «Сохранить».
Выводить всё это мы будем простейшую вьюшку, имя которой config.php:
<?php $this->breadcrumbs = array( 'Администрирование', 'Настройки приложения', ); ?> <div class="form"> <?php echo $form; ?> </div>
Ну тут совсем всё тривиально. Разве что для красоты оставим breadcrumbs.
А вот теперь будет самое интересное. В контроллере мы свяжем нашу модель с произвольным количеством полей и спец. табличку БД, хранящую пары «ключ->значение». Связью как я и говорил будет сложить модуль EConfig. Файл WtsController.php:
class WtsController extends Controller { public function actionIndex() { $model = new WtsConfigForm; foreach ($model->attributes as $attr => $val) { $model->$attr = Yii::app()->getModule('configpage')->config->get($attr); } $form = new CForm('configpage.views.wts.configForm', $model); if ($form->submitted('configPage') && $form->validate()) { foreach ($model->attributes as $attr => $val) { Yii::app()->getModule('configpage')->config->set($attr, $val); } $this->render('config', array('form' => $form)); } else { $this->render('config', array('form' => $form)); } } }
Что здесь происходит. В actionIndex (чтобы не плодить лишнего) мы создаём экземпляр модели, заполняем её значениями из БД, причём если в БД отсутствует требуемое значение, то в поле проставляется значение null, затем мы создаём форму, используя наше описание и экземпляр модели.
А дальше проверяем — если есть данные из браузера — если таковые найдутся, то модель самостоятельно загрузит их, после чего эти данные будут записаны в БД и страница настроек будет вновь показана пользователю.
Кстати да, заметьте, что я за ненадобностью не описал правил фильтрации пользователей. Вы этого сделать не забудьте, а то все смогут поназаписывать настроек в базу.
Остаются мелочи. Подключить и начать использовать модуль.
Подключаем
Подключить модуль проще простого. Просто вписываем следующий код в раздел modules главного файла конфигурации приложения (main.php).
... 'modules' => array( 'configpage' => array( 'components' => array( 'config' => array( 'class' => 'EConfig', 'strictMode' => false, ), ), ), ), ...
Вот и всё, модуль подключен.
Используем
Естественно сама по себе страничка нам нафиг не упала, нам нужен какой-то способ доступа к информации хранящейся в БД. Для данного конкретного примера мы можем реализовать загрузку данных в файле index.php нашего приложения:
$app = Yii::createWebApplication($config); function loadSettings() { Yii::app()->getModule('gii')->password = Yii::app()->getModule('configpage')->config->get('giiPassword'); Yii::app()->name = Yii::app()->getModule('configpage')->config->get('applicationName'); Yii::app()->params['adminEmail'] = Yii::app()->getModule('configpage')->config->get('adminEmail'); } loadSettings(); $app->run();
То есть, мы создаём экземпляр приложения, оно подгружает модули и настройки, затем мы перезаписываем некоторые из настроек и только после этого выполняем приложение.
Как-то так. Единственное, что мне не нравится — это строка вызова метода get:
Yii::app()->getModule('configpage')->config->get('applicationName');
Уж слишком она длинная. К сожалению придумать как её укоротить я пока не могу. Может кто подскажет?
Ну и куда же без картинок. Вот что у нас примерно должно получиться в итоге:
За картинку кстати не ругайте, если найдёте сходство с данным проектом. OpenSource, все дела, можно использовать чужие наработки. В данном случае — понравилось расположение панельки слева. В остальном никакого сходства =). Ди а вообще, Twitter Bootstrap он везде одинаковый.
Из позитивного
Я по специализации вообще-то нифига не web-разработчик, но почему-то в последнее время всё больше приходится заниматься именно данным видом кодинга. И почему-то мне нравится, куда проще чем Qt и C++ =). Когда я открыл для себя такие вещи как генерация кода, фреймворк Yii, Twitter Bootstrap и множество других ништяков, я понял что проекты под web могут вылетать из под пера более-менее опытного разработчика как горячие пирожки — по три штуки в месяц.
Так что кипящие в соседних топиках дискуссии о постоянной нехватке квалифицированных кадров — какая-то глупость.
Современные средства разработки настолько просты, что 90% работы можно выполнить никогда так и не узнав разницы между MySql индексами типа BTree и hash. А оставшиеся 10% всегда можно где-то подглядеть.
Ну да ладно, всё это лирика.
Что ещё хотелось бы отметить
Расширить данный модуль очень легко — достаточно добавить ещё по одному экзепляру контроллера, модели, описания формы и вьюшки. А можно обойтись и меньшими усилиям — новый action, описалово формы и модель. Вьюшку можно юзать ту же самую. И тогда у вас будет уже две-три-десять независимых друг от друга страниц настроек.
Для меня кстати унификация и оптимизация — это вообще болезнь, так что хотелось бы конечно прикрутить ко всему этому интерфейс по редактированию полей формы настроек прямо в браузере, но это уже в каком-нибудь другом проекте.
Вообще после года работы с Yii у меня накопился целый ящик всяких примеров, архитектурных решений и извращений, всё собираюсь их по человечески описать, но как обычно время, время…
Вроде всё. Вопросы? Предложения?
ссылка на оригинал статьи http://habrahabr.ru/post/172737/
Добавить комментарий