Создание админки. ч1. Создание модуля для работы с настройками(данными) из БД.
Вступление
Столкнулся с тем, что не удобно настраивать сайт, постоянно прописывая все настройки в config-файлах, поэтому решил сделать админку, где можно будет менять настройки сайта. Так же поделюсь информацией для создания своего модуля работы с данными.
Тем, кто еще не создавал модулей, лучше сначала прочитать
Хранилище данных настроек
Настроек может быть несколько видов, поэтому они будут разделены на группы для удобства. Для хранения настроек будет использоваться таблица с двумя полями, одно имя группы настроек, другое значение в котором будет хранится строка-ассоциативный массив.
CREATE TABLE `prefix_core` (
`pref_name` varchar(100) NOT NULL,
`pref_value` text NOT NULL,
UNIQUE KEY `pref_name` (`pref_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Т.е. хранимое значение будет, например
pref_name = 'site', pref_value ='array (
'SITE_NAME' => 'livestreet',
'SITE_KEYWORDS' => 'livestreet, cms, open source',
'SITE_DESCRIPTION' => 'livestreet - open source cms',
)'
Модуль работы с настройками
Далее создаем модуль работы с настройками сайта.
По пути «classes\modules\» название «prefs», в каталоге создаем 3 файла.
Prefs.class.php — класс для работы с настройками (функции модуля)
mapper\Prefs.mapper.class.php — класс доступа к данным (запись/чтение данных из базы данных)
entity\Site.entity.class.php — сущность данных (описание полей к которым сможем обращаться)
Описание сущности. \entity\Site.entity.class.php
Как ни странно, начну с описания сущности, в ней представлены 3 поля (настройки) Имя сайта, Ключевые слова и Описание сайта и соответственно методы работы с данными: get получают значение, а set записывают данные в сущность.
Причем, в реализации данного модуля сделано так, что если не установлены настройки через админку, то они будут возвращаться как были описаны файле настроек.
class PrefsEntity_Site extends Entity {
public function getSiteName() {
if (isset($this->_aData['SITE_NAME'])){
return $this->_aData['SITE_NAME'];
}
return SITE_NAME;
}
public function getSiteKeyWords() {
if (isset($this->_aData['SITE_KEYWORDS'])){
return $this->_aData['SITE_KEYWORDS'];
}
return SITE_KEYWORDS;
}
public function getSiteDescription() {
if (isset($this->_aData['SITE_DESCRIPTION'])){
return $this->_aData['SITE_DESCRIPTION'];
}
return SITE_DESCRIPTION;
}
public function getArray(){
return $this->_aData;
}
public function setSiteName($data) {
$this->_aData['SITE_NAME']=$data;
}
public function setSiteKeyWords($data) {
$this->_aData['SITE_KEYWORDS']=$data;
}
public function setSiteDescription($data) {
$this->_aData['SITE_DESCRIPTION']=$data;
}
}
Соответственно если будите создать свой модуль достаточно будет написать так:
class <ИмяКлассаМодуля>Entity_<ИмяСущности> extends Entity {
public function getЛогичноеИмя() {
return $this->_aData['Имя_поля_в_базе'];
}
public function setЛогичноеИмя($data) {
$this->_aData['Имя_поля_в_базе']=$data;
}
}
Описание доступа к данным \mapper\Prefs.mapper.class.php
Тут все просто, данные настроек получаются из базы, причем по умолчанию всех групп, а далее методом get получаются настройки конкретной группы настроек, за сохранение настроек отвечает метод set.
class Mapper_Prefs extends Mapper {
private $prefVals;
private $prefArrays;
/**
* Проверяем есть ли уже такой раздел с настройками
* @param name - имя настройки
*/
public function сheckPrefs($name = "")
{
$sql = "SELECT pref_name, pref_value from ".DB_TABLE_CORE." where pref_name = '$name'";
if (!$aRow=$this->oDb->selectRow($sql)) {
return false;
}
return true;
}
/**
* Устанавливаем настройки
* @param name - имя настройки
* @param val - значение настройки
*/
public function set($name = "", $val) {
$val = addslashes($val);
// Скрипт обновления
$sql = "UPDATE ".DB_TABLE_CORE."
SET
pref_value='$val'
WHERE
pref_name = '$name'
";
// Скрипт вставки
$sql_ins = "INSERT INTO ".DB_TABLE_CORE." (pref_name,pref_value) VALUES('$name','$val')";
if($this->сheckPrefs($name))
{
$this->oDb->query($sql);
} else{
$this->oDb->query($sql_ins);
}
}
/**
* Получение настроек по имени
* @param name - имя настройки
*/
public function get($Name) {
if(isset($this->prefVals[$Name])){
return $this->prefVals[$Name];
} else {
return false;
}
}
/**
* Получаем данные настроек, по умолчанию выбираются данные всех настроек
* @param Preflist - массив с перечислением нужных настроек
*/
public function ExtractPrefs($Preflist = "") {
$lim = "";
if(is_array($Preflist))
{
foreach($Preflist as $v)
{
$lim .= ($lim ? " OR pref_name='{$v}'" : "pref_name='{$v}'");
}
}
if (strlen($lim)){
$lim = "where $lim";
}
$sql = "SELECT pref_name, pref_value from ".DB_TABLE_CORE." $lim";
if ($row =$this->oDb->select($sql)){
foreach($row as $key => $value){
$this->prefVals[$value['pref_name']] = $value['pref_value'];
}
}
return $this->prefVals;
}
}
Для создания собстевенного модуля для работы с данным достаточно будет написать 3 функции
class Mapper_<ИмяКлассаМодуля> extends Mapper {
public function ФункцияВыборкиДанных() {
}
public function ФункцияВставкиДанных() {
}
public function ФункцияОбновленияДанных() {
}
}
Кто хочет узнать синтаксис и возможности работы с данными, то вам
Описание основного модуля Prefs.class.php
Функции модуля позволяют «на высоком уровне» работать с данными. Например, getPrefs возвращает уже наполненную сущность данными, setPrefs сохраняет данные, readArray преобразует данные из строки-массива в «нормальный» ассоциативный массив, writeArray делает обратную операцию.
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__));
require_once('mapper/Prefs.mapper.class.php');
class Prefs extends Module{
protected $oMapperPrefs;
/**
* Инициализация
*/
public function Init() {
$this->oMapperPrefs=new Mapper_Prefs($this->Database_GetConnect());
}
/**
* Функция которая возвращает сущность со значениями
* @param $name - имя настройки
*/
public function getPrefs($name = '') {
$this->oMapperPrefs->ExtractPrefs(); //array('site','plugins')
$PrefData = $this->oMapperPrefs->get($name);
return new PrefsEntity_Site($this->readArray($PrefData));
}
/**
* Сохранение значений
* @param name - имя настройки
* @param oPrefs - объект настроек
*/
public function setPrefs($name, PrefsEntity_Site $oPrefs) {
$PrefData = $oPrefs->getArray($oPrefs);
$this->oMapperPrefs->set($name,$this->writeArray($PrefData, false));
}
/**
* Записываем строку-массив
* @param ArrayData - массив
* @param AddSlashes - экранировать слешем кавычки?
*/
private function writeArray($ArrayData, $AddSlashes = true) {
if (!is_array($ArrayData)) {
return false;
}
$Array = var_export($ArrayData, true);
if ($AddSlashes == true) {
$Array = addslashes($Array);
}
return $Array;
}
/**
* Читаем массив из строки-массива
* @param ArrayData - строка-массив
*/
private function readArray($ArrayData) {
if ($ArrayData == ""){
return false;
}
$data = "";
$ArrayData = '$data = '.trim($ArrayData).';';
@eval($ArrayData);
if (!isset($data) || !is_array($data)) {
trigger_error("Кривые данные на входе - <br />".htmlentities($ArrayData), E_USER_ERROR);
return false;
}
return $data;
}
}
Для создании собственного класса модуля прочитайте
protected $oMapper<ИмяКлассаМодуля>;
public function Init() {
$this->oMapper<ИмяКлассаМодуля>=new Mapper_<ИмяКлассаМодуля>($this->Database_GetConnect());
}
далее функции доступа к данным можно вызывать, например так: $this->oMapper<ИмяКлассаМодуля>->ФункцияВыборкиДанных();
P.S> Наверняка многое можно оптимизировать.
P.S.S> постарался по компактнее описать и информативнее комментировать код, надеюсь все понятно, если нет, пишите, отвечу на вопросы.
В следующей статье будет описано как создаются меню и будут использованы функции ранее описанного модуля.
5 комментариев
добавить строчку еще define('DB_TABLE_CORE',DB_PREFIX_TABLE.'core');
Всем привет, пишу свой первый комментарий.
Преодолел установку LS на денвер ) было не совсем уж сложно, но проблемно.
Я только начинаю изучать все эти при мудрости, но скажите куда писать вот это
CREATE TABLE `prefix_core` (
`pref_name` varchar(100) NOT NULL,
`pref_value` text NOT NULL,
UNIQUE KEY `pref_name` (`pref_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
в файл modules/Mytest.class.php надо добавить
И тогда я смогу делать запросы к базе как из файла модуля так и из экшна?
функция:
$this -> Database_GetConnect()?..