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

в 9:26, , рубрики: config, 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 у меня накопился целый ящик всяких примеров, архитектурных решений и извращений, всё собираюсь их по человечески описать, но как обычно время, время…

Вроде всё. Вопросы? Предложения?

Автор: vitaly_KF

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js