Pull to refresh

Простенькая страница настроек для Yii-приложения

PHP *Yii *
Привет.

Хочу поделиться небольшим модулем, предназначенным для создания страницы настроек в своём приложении. А заодно узнать у сообщества, что в нём можно было бы улучшить.

Задача по своей идее простая — сделать табличку в БД, хранящую параметры типа «ключ -> значение», а к ней сделать страничку редактирования, позволяющую изменять данные значения. ну и конечно же реализовать программный интерфейс для доступа к параметрам хранимым в БД.

Срок реализации — около получаса. В интернете почему-то готового решения было не найти. Исправим положение, авось кому пригодится.

Делать будем на конкретном примере. Допустим, нам необходимо хранить такие настройки: Имя приложения, Описание приложения, Пароль для 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');

Уж слишком она длинная. К сожалению придумать как её укоротить я пока не могу. Может кто подскажет?

Ну и куда же без картинок. Вот что у нас примерно должно получиться в итоге:
image

За картинку кстати не ругайте, если найдёте сходство с данным проектом. OpenSource, все дела, можно использовать чужие наработки. В данном случае — понравилось расположение панельки слева. В остальном никакого сходства =). Ди а вообще, Twitter Bootstrap он везде одинаковый.

Из позитивного


Я по специализации вообще-то нифига не web-разработчик, но почему-то в последнее время всё больше приходится заниматься именно данным видом кодинга. И почему-то мне нравится, куда проще чем Qt и C++ =). Когда я открыл для себя такие вещи как генерация кода, фреймворк Yii, Twitter Bootstrap и множество других ништяков, я понял что проекты под web могут вылетать из под пера более-менее опытного разработчика как горячие пирожки — по три штуки в месяц.

Так что кипящие в соседних топиках дискуссии о постоянной нехватке квалифицированных кадров — какая-то глупость.

Современные средства разработки настолько просты, что 90% работы можно выполнить никогда так и не узнав разницы между MySql индексами типа BTree и hash. А оставшиеся 10% всегда можно где-то подглядеть.

Ну да ладно, всё это лирика.

Что ещё хотелось бы отметить


Расширить данный модуль очень легко — достаточно добавить ещё по одному экзепляру контроллера, модели, описания формы и вьюшки. А можно обойтись и меньшими усилиям — новый action, описалово формы и модель. Вьюшку можно юзать ту же самую. И тогда у вас будет уже две-три-десять независимых друг от друга страниц настроек.

Для меня кстати унификация и оптимизация — это вообще болезнь, так что хотелось бы конечно прикрутить ко всему этому интерфейс по редактированию полей формы настроек прямо в браузере, но это уже в каком-нибудь другом проекте.

Вообще после года работы с Yii у меня накопился целый ящик всяких примеров, архитектурных решений и извращений, всё собираюсь их по человечески описать, но как обычно время, время…

Вроде всё. Вопросы? Предложения?
Only registered users can participate in poll. Log in, please.
Стоит ли мне дальше писать про Yii?
75.09% Да 434
6.75% Нет 39
9% Больше кода, меньше слов! 52
3.11% Ничерта не понятно, не пиши больше. 18
6.06% Зачем здесь такая элементарщина? 35
578 users voted. 162 users abstained.
Tags:
Hubs:
Total votes 34: ↑27 and ↓7 +20
Views 20K
Comments Comments 14