Конфиги в CakePHP из базы данных

Рано или поздно придется столкнуться с тем что Вам могут понадобиться какие либо переменные в вашем сайте на CakePHP, которые необходимо относительно часто изменять и которые используются в нескольким местах. Самый лучший способ, по моему мнению, это использовать компонент Configure, в который можно добавлять любые переменные, а потом считывать их когда они необходимы.

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

Для начала Вам необходимо создать таблицу в базе данных, для MySQL код будет выглядеть так:

CREATE TABLE  `configs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
`desc` varchar(255) DEFAULT NULL,
`type` varchar(255) NOT NULL DEFAULT 'string',
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Настройки ППО';

Затем нам необходимо сделать механизм для считывания данных из БД. Причем  данные нам необходимо получать как можно раньше при инициализации приложения. В этом нам поможет файл /app/config/bootstrap.php и созданный нами вендор. Начнем с последнего.

Создадим файл /app/vendors/imp_config.php со следующим содержимым:

if (defined('CORE_UPDATED')) {
if (($results = Cache::read('db_configs')) === false) {
App::import('Core','ConnectionManager');
$db =& ConnectionManager::getDataSource('default');
$results = $db--->query("SELECT Config.name, Config.value, Config.type FROM configs Config");
Cache::write('db_configs', $results);
}
foreach($results as $row) {
switch ($row['Config']['type']) {
case 'boolean':
Configure::write($row['Config']['name'], ($row['Config']['value']=='1')?true:false);
break;
case 'string':
default:
Configure::write($row['Config']['name'], $row['Config']['value']);
}
}
}

Вообще этот файл мне достался от коллеги, которая нашла данный механизм где то на просторах интернета, так что если кто то признает в нем остатки своего кода - пишите.

Поскольку при каждом обращении пользователя к серверу перечитывать все нужные и ненужные конфиги из БД накладно, я добавил кеширование. Так же переменные могут быть разных типов (на данный момент реализованы логические и строковые).

В /app/config/core.php объявите константу CORE_UPDATED чтобы наша конструкция работала. Управляя значением этой переменной Вы можете управлять включением и выключением этой функции.

DEFINE('CORE_UPDATED',true);

Теперь в bootstrap.php добавляем:

require_once( ROOT . DS . 'app'. DS .'vendors'. DS .'imp_config.php' );

Все, теперь данные будут читаться из БД и записываться в кеши, поэтому как только Вы обновите переменные, Вам надо будет почистить кеши.

Теперь осталось сделать только удобный интерфейс для внесения данных и автоматической очистки кеша.

Модель (config.php):

class Config extends AppModel {
var $name = 'Config';
}

Контроллер (configs_controller.php):

class ConfigsController extends AppController {
var $name = 'Configs';
var $helpers = array('Html', 'Form');
var $type_vars = array('string' =--> 'Строковый', 'boolean' => 'Логический');
function beforeFilter()  {
parent::beforeFilter();
}
function index() {
$this->Config->recursive = 0;
$this->set('configs', $this->paginate());
}
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid Config', true));
$this->redirect(array('action' => 'index'));
}
$this->set('config', $this->Config->read(null, $id));
}
function add() {
if (!empty($this->data)) {
$this->Config->create();
if ($this->Config->save($this->data)) {
if (Cache::delete('db_configs')) {
$this->Session->setFlash(__('Переменная успешно сохранена', true));
} else {
$this->Session->setFlash(__('Переменная успешно сохранена. Кеш не очищен.', true));
}
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('Переменная не сохранена. Пожалуйста, попробуйте еще.', true));
}
}
$this->set('types', $this->type_vars);
}
function edit($id = null) {
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid Config', true));
$this->redirect(array('action' => 'index'));
}
if (!empty($this->data)) {
if ($this->Config->save($this->data)) {
if (Cache::delete('db_configs')) {
$this->Session->setFlash(__('Переменная успешно сохранена', true));
} else {
$this->Session->setFlash(__('Переменная успешно сохранена. Кеш не очищен.', true));
}
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('Переменная не сохранена. Пожалуйста, попробуйте еще.', true));
}
}
if (empty($this->data)) {
$this->data = $this->Config->read(null, $id);      $this->set('types', $this->type_vars);
}
}
function delete($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid id for Config', true));
$this->redirect(array('action' => 'index'));
}    if ($this->Config->del($id)) {
if (Cache::delete('db_configs')) {
$this->Session->setFlash(__('Переменная успешно удалена', true));
} else {
$this->Session->setFlash(__('Переменная успешно удалена. Кеш не очищен.', true));
}
$this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Переменная не удалена. Пожалуйста, попробуйте еще.', true));
$this->redirect(array('action' => 'index'));
}
}

Вьюхи можно сгенерировать с помощью cake bake, но вот то что сделал я. index.ctp:

<div><h2><?php __('Настройки');?></h2><p><!?php echo $paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)));?></p><tr<?php echo="" $class;?="">>    <table cellpadding="0" cellspacing="0"><tbody><tr>  <th><?php echo $paginator->sort('id');?></th>  <th>sort('name');?></th>  <th><?php echo $paginator->sort('value');?></th>  <th><?php echo $paginator->sort('desc');?></th>  <th><?php echo $paginator->sort('type');?></th>  <th><?php echo $paginator->sort('created');?></th>  <th><?php echo $paginator->sort('modified');?></th>  <th><?php __('Actions');?></th></tr><?php $i = 0; foreach ($configs as $config):  $class = null;  if ($i++ % 2 == 0) {    $class = '';  } ?>  <tr><td>      <?php echo $config['Config']['id']; ?>    </td>    <td>      <?php echo $config['Config']['name']; ?>    </td>    <td>      <?php echo $config['Config']['value']; ?>    </td>    <td>      <?php echo $config['Config']['desc']; ?>    </td>   <td>      <?php echo $config['Config']['type']; ?>    </td>    <td>      <?php echo $config['Config']['created']; ?>    </td>    <td>      <?php echo $config['Config']['modified']; ?>    </td>   <td>      <?php echo $html--->link(__('View', true), array('action' => 'view', $config['Config']['id'])); ?>      <?php echo $html--->link(__('Edit', true), array('action' => 'edit', $config['Config']['id'])); ?>      <?php echo $html->link(__('Delete', true), array('action' => 'delete', $config['Config']['id']), null, sprintf(__('Are you sure you want to delete # %s?', true), $config['Config']['id'])); ?>    </td>  </tr><?php endforeach; ?></tbody></table>

Автор: Сергей Степанов

Поделиться @

Пока нет коментариев. Будьте первым!