Как создать свой модуль
- Создаем таблицу в БД
- Панель администрирования
- Вкладки для части модуля и конфигурация
- Пользовательская часть
В данном разделе документации рассказано как создать модуль для DIAFAN.CMS. На первый взгляд это легко, но, как и везде, есть свои особенности. Приложение к данному разделу – каркас модуля, который можно скачать по этой ссылке.
Модуль – набор файлов в папке modules/имя_модуля. Подробнее об устройстве модуля.
В нашем примере модуль будет называться example. Все файлы модуля будут храниться в папке modules/example.
Для того чтобы подключить наш сырой модуль к DIAFAN.CMS, необходимо сделать записи в таблицах {modules} и {admin}. Для этого в файле example.install.php прописываем:
Пример:
// записи в таблице {modules}
public $modules = array(
array(
"name" => "example",
"admin" => true,
"site" => true,
"site_page" => true,
),
);
// меню административной части
public $admin = array(
array(
"name" => "Название модуля",
"rewrite" => "example",
"group_id" => "1",
"sort" => 5,
"act" => true,
"children" => array(
array(
"name" => "Настройки",
"rewrite" => "example/config",
),
)
),
);
Теперь модуль появится в списке модулей для установки в разделе «Модули и БД» – «Установка модулей». Устанавливаем модуль.
Следующим шагом будет добавление нашего модуля на какую-нибудь страницу сайта. Идем в админку, создаем обычную текстовую страницу и во вкладке «Дополнительно» прикрепляем к ней наш новый модуль.
Все, модуль готов к использованию!
Правда пока он ничего не делает, поэтому давайте сделаем его функциональным.
Давайте сделаем модуль, который будет позволять размещать объявления на сайте.
Все что вы прочитаете ниже не жесткие пошаговые инструкции и выполнять действия в том порядке, котором это сделано здесь не обязательно. У каждого программиста свой подход к решению поставленной задачи и необходимо уметь самостоятельно думать, чтобы все получалось.
Создаем таблицу в БД
Для начала определимся с задачами, которые должен выполнять модуль:
- позволять зарегистрированным пользователям сайта добавлять объявления
- позволять администратору редактировать объявления
- позволять администратору размещать объявления
Объявления будут размещены в базе данных в таблице ВАШ_ПРЕФИКС_example, и нам необходимо разработать ее структуру.
Префикс по умолчанию – diafan_. Вы могли переименовать его при установке DIAFAN.CMS, поэтому создавайте таблицу по подобию других таблиц в БД.
Для работы с БД можно использовать phpMyAdmin, который обычно есть на хостинге.
- user_id – id нашего зарегистрированного пользователя, который добавил объявление
- created – время создания
- text – текст объявления
Таблица с информацией о пользователях у нас уже есть, это модуль по умолчанию «Пользователи», поэтому мы будем использовать эту информацию. Нам достаточно хранить только идентификатор пользователя в поле user_id нашей новой таблицы.
Таблицу описываем в файле example.install.php, чтобы можно было использовать модуль повторно.
Пример:
public $tables = array(
array(
"name" => "example",
"fields" => array(
array(
"name" => "id",
"type" => "INT(11) UNSIGNED NOT NULL AUTO_INCREMENT",
),
array(
"name" => "user_id",
"type" => "INT(11) UNSIGNED NOT NULL DEFAULT '0'",
),
array(
"name" => "created",
"type" => "INT(10) UNSIGNED NOT NULL DEFAULT '0'",
),
array(
"name" => "text",
"type" => "text NOT NULL DEFAULT ''",
),
),
"keys" => array(
"PRIMARY KEY (id)",
),
),
);
Панель администрирования
Начнем разработку нашего модуля с админки, перед этим не забыв включить «Режим разработки» в параметрах сайта, чтобы видеть лог наших возможных ошибок.
Обязательно включайте режим разработки и отключайте кэширование в настройках сайта при любых правках любых модулей.
Если открыть админку нашего нового модуля, мы ничего не увидим, потому что мы ничего не описали. Когда административная часть DIAFAN.CMS подключает администрирование модуля, то ядро системы сразу автоматически подключает для управления информацией модуля все действия. В модуле для начала достаточно просто описать, что и как надо выводить и что редактировать.
Откроем файл example.admin.php и опишем класс Example_admin:
Пример:
class Example_admin extends Frame_admin
{
// название таблицы бд, по которой будет формироваться список
public $table = 'example';
// описание полей таблицы
public $variables = array (
'main' => array (
'created' => array(
'type' => 'datetime',
'name' => 'Дата создания',
),
'user_id' => array(
'type' => 'select',
'name' => 'Автор',
),
'text' => array(
'type' => 'editor',
'name' => 'Текст объявления',
),
),
);
// описание полей в списке
public $variables_list = array (
'checkbox' => '',
'name' => array(
'name' => 'Текст объявления',
),
);
// ссылка на добавление нового объявления
public function show_add()
{
$this->diafan->addnew_init('Добавить объявление');
}
// функция, которая определяет что выводит модуль при открытии
public function show()
{
// список объявлений
$this->diafan->list_row();
}
}
Свойство класса $table определяет в какой таблице будут храниться наши объявления, массив $variables описывает каждое поле таблицы, массив $variables_list описывает какие поля и как будут выводиться в списке, функция show() выводит список объявлений.
Описывая поля, мы показываем DIAFAN.CMS, что мы хотим править и в каком виде. Заметьте, что порядок следования пунктов повторяется и на странице в админке. Для редактирования пользователя удобнее сделать выпадающий список, где были бы имена зарегистрированных пользователей. Для этого задаем дополнительный атрибут select_db, в котором указываем, в какой таблице базы данных и какие данные брать.
Пример:
// описание полей таблицы
public $variables = array (
'main' => array (
'created' => array(
'type' => 'datetime',
'name' => 'Дата создания',
),
'user_id' => array(
'type' => 'select',
'name' => 'Автор',
'select_db' => array(
'table' => 'users',
'name' => 'fio',
'where' => "trash='1'",
),
),
'text' => array(
'type' => 'editor',
'name' => 'Текст объявления',
),
),
);
Теперь опишем как будет выглядеть список объявлений. Для этого нужно их добавить в массив $variables_list.
Пример:
// описание полей в списке
public $variables_list = array (
'checkbox' => '',
'created' => array(
'name' => 'Дата и время',
'type' => 'datetime',
'sql' => true,
),
'name' => array(
'name' => 'Текст объявления',
),
'user_id' => array(
'name' => 'Пользователь',
'type' => 'string',
'sql' => true,
),
'actions' => array(
'del' => true,
),
);
Мы добавили два поля из базы данных (атрибут sql означает, что будет брать данные из базы). И указали формат, в котором данные выводяться. И добавили действие «Удалить».
И последнее. Мы должны указать, что основное поле у нас называется text (по умолчанию name):
Пример:
'name' => array(
'name' => 'Текст объявления',
'variable' => 'text',
),
Все, этого вполне достаточно чтобы выводить список объявлений, добавлять, редактировать и сохранять их.
Ура, теперь у нас в списке выводится объявление, время добавления и id пользователя.
Как вы видите, функция list_row выводит поля из базы данных в том виде, в котором они в нее записаны, но это можно легко исправить!
Напишем простую функцию, переопределяющую системное отображение. Формат названия функции таков: list_variable_переменная($row), где $row – массив значений для текущего элемента:
Пример:
public function list_variable_user_id($row)
{
return '<div>'.DB::query_result("SELECT fio FROM {users} WHERE id=%d", $row['user_id']).'</div>';
}
То есть, если DIAFAN.CMS обнаруживает эти функции с названием по маске list_variable_*, она понимает, что поле user_id нужно выводить так, как описано в этой функции.
Внимание! Пример показывает как использовать функцию list_variable_(). Оптимальнее для этой задачи использовать тип *select с описанным уже в $variables
атрибутом select_db.
Идем далее. Расширим функциональность нашего модуля, чтобы наши объявления сортировались, удалялись и активировались по нашему велению.
В базу данных добавим поля удаления в корзину, активности и сортировки:
И пропишем настройки в $variables_list
.
Пример:
// описание полей в списке
public $variables_list = array (
'checkbox' => '',
'sort' => array(
'name' => 'Сортировка',
'type' => 'numtext',
'desc' => true,
'sql' => true,
'fast_edit' => true,
),
'created' => array(
'name' => 'Дата и время',
'type' => 'datetime',
'sql' => true,
),
'name' => array(
'name' => 'Текст объявления',
),
'user_id' => array(
'name' => 'Пользователь',
'type' => 'string',
'sql' => true,
),
'actions' => array(
'act' => true,
'trash' => true,
),
);
Теперь у нас в списке объявлений появятся иконки удаления, активности, и их можно будет сортировать.
Также не стоит забывать про переменную $variables_filter, которая позволяет нам добавлять собственные параметры в фильтре.
Давайте с ее помощью для примера организуем фильтр объявлений по имени пользователя.
Пример:
public $variables_filter = array (
'user_id' => array(
'type' => 'select',
'name' => 'Искать по пользователю',
),
);
Значения для списка берем из базы данных. Таблицу базы данных берем из атрибута select_db в массиве $variables
.
В общем, вид представления административной части модуля зависит лишь от вашей фантазии. Никто не принуждает вас использовать функцию list_row, вы можете написать любой собственный обработчик.
Мощным средством расширения функционала модуля является тип function.
Он позволяет определять пользовательские функции для редактирования и сохранения поля. Давайте сделаем так, чтобы при редактировании user_id имя пользователя у нас было не просто выпадающим списком, а выбиралось с помощью AJAX-запроса:
Переназначим $variables, укажем для user_id тип не select, а function.
Пример:
public $variables = array (
'main' => array (
...
'user_id' => array(
'type' => 'function',
'name' => 'Автор',
),
...
),
);
И объявим две функции
Пример:
public function edit_variable_user_id(){}
public function save_variable_user_id(){}
Займемся визуальным отображением редактирования поля user_id и будем править функцию edit_variable_user_id.
Пример:
public function edit_variable_user_id()
{
echo '<div class="unit">
<div class="infofield">Нажми</div>
<div class="user_id" rel="'.$this->diafan->value.'"><b>ЗДЕСЬ</b></div>
</div>';
}
Напишем простой jQuery обработчик, отправляющий Ajax-запрос. Для этого создадим файл modules/example/admin/js/example.admin.edit.js. Этот JS-файл подключиться для формы редактирования автоматически. Созданный файл будет следующего содержания:
Пример:
$(".user_id").click(function(){
var user_id = $(this).attr('rel');
diafan_ajax.init({
data:{
action: "user",
module: "example",
user_id: user_id
},
success: function(response) {
alert(response.name);
}
});
});
Обработчик по нажатию на элемент с классом user_id отправляет AJAX-запрос текущей странице с параметрами module, action и user_id. Ajax-запрос отправляем через обработчик diafan_ajax, чтобы были добавлен идентификационный хэш и его проверка.
Теперь нам нужно написать example.admin.action.php
Пример:
class Example_admin_action extends Action_admin
{
public function init()
{
if (! empty($_POST['user_id']))
{
$this->result["name"] = DB::query_result("SELECT fio FROM {users} WHERE id=%d", $_POST['user_id']);
}
else
{
$this->result["name"] = 'ошибка';
}
}
}
Файл example.admin.action.php подключается лишь тогда, когда одновременно отправляются POST переменные action и module. Значение переменной module должно соответствовать названию нашего модуля. При соблюдении этих условий подключиться функция init()
, в которой должно быть описано обработка запроса. Данные, сохраненные в переменной $this->result
автоматически будут отправлены обратно в JSON-формате.
Теперь доработаем функцию save_variable_user_id, в которой происходит сохранение поля. Тут вы можете вставлять данные в другую таблицу, обрабатывать самостоятельно переменные $_POST, дважды досчитать до бесконечности.
Для того чтобы записать данные в таблицу {example}, которую использует наш модуль, можно сделать такую хитрость:
Пример:
public function save_variable_user_id()
{
$this->diafan->set_query("user_id=%d");
$this->diafan->set_value(1);
}
Таким образом, мы добавили к SQL запросу UPDATE поле user_id со значением 1.
Текущую выборку из базы данных можно получить через функцию $this->diafan->values()
. Например, $this->diafan->values('site_id')
вернет значение поля site_id
.
Как вы могли сами увидеть, function предоставляет огромные возможности для расширения функционала административной части модуля, все зависит от вашей фантазии и правильного крепления рук к телу.
Еще есть замечательный тип в $variables
– module. Он означает, что необходимо подключить к редактированию сторонний модуль.
Как это работает.
Там где нужно подключить модуль example, например, при редактировании новостей в файле modules/news/admin/news.admin.php в $variables
прописываем.
Пример:
public $variables = array(
'main' => array(
'example' => 'module',
…
),
…
);
При редактировании новости DIAFAN.CMS будет искать файл modules/example/admin/example.admin.inc.php, где описаны функции edit()
и save()
.
Это работает практически так же, как и тип function, только между модулями.
Вкладки для части модуля и конфигурация
В DIAFAN.CMS административную часть модуля можно еще дополнять различными расширениями, вкладками (подразделами модуля, например, как заказы в магазине). Загляните в папку modules/shop/admin
Делается это так: создается файл example.admin.bolt.php и в нем инициализируется класс
class Example_admin_bolt extends Frame_admin
Потом мы идем в http://site.ru/admin/admin/ и добавляем подраздел нашему модулю с псевдоссылкой example/bolt. Количество расширений модуля зависят лишь от вашей фантазии.
Есть еще особый тип расширения – конфигурация.
Регистрируется он так же, как и обычное расширение: в http://site.ru/admin/admin/ добавляем подраздел «Настройки» с псевдоссылкой example/config.
Основной его отличительной особенностью является настройка в $config.
public $config = array('config');
Если она установлена, то сохранение происходит не в таблицу, указанную в
$table
, а в таблицу {config}, для доступа к которой предусмотрена специальная функция ядра configmodules, которую можно вызвать откуда угодно.
Пользовательская часть
Если мы подключили модуль к странице сайта, то при ее открытии из контроллера
example.php вызывается функция init()
.
Как можно видеть из примера, при инициализации модуля подключается модель. Результат исполнения
записывается в переменную $this->result
. После подключается шаблон, указанный в $this->result["view"]
.
В примере $this->result["view"] = 'show'
, значит подключается файл modules/example/views/example.view.show.php.
Если в модуле будут использоваться перменные, передаваемые в URL, то их нужно указать в массиве rewrite_variable_names.
Пример:
public $rewrite_variable_names = array('page', 'show');
Наш модуль все равно сыроват. При заходе на страницу с прикрепленным модулем мы ничего не видим. Давайте сделаем список объявлений, разбитый на страницы. При нажатии на объявление оно откроется в отдельном окне, в котором можно будет вписать комментарий.
Это не сложно, не пугайтесь :)
Пример:
public function show()
{
// данные будем кэшировать
$cache_meta = array(
"name" => "list", // метка кэша
"page" => $this->diafan->page > 1 ? $this->diafan->page : 1,
);
// если данных нет в кэше занесем их
if (!$this->result = $this->diafan->_cache->get($cache_meta, 'example'))
{
$this->result = array();
////navigation//
$this->diafan->_paginator->nen = DB::query_result("SELECT COUNT(id) FROM {example} WHERE act='1' AND trash='0'");
$this->result["paginator"] = $this->diafan->_paginator->get();
////navigation///
$rows = DB::query_range_fetch_all("SELECT id, created, text FROM {example} WHERE act='1' AND trash='0' ORDER BY created DESC, id DESC",
$this->diafan->_paginator->polog, $this->diafan->_paginator->nastr);
foreach($rows as $row)
{
$row['created'] = $this->format_date($row['created'], 'example');
$row['link'] = $this->diafan->_route->link($this->diafan->_site->id, $row["id"], 'example');
$this->result['rows'][] = $row;
}
//сохранение кэша
$this->diafan->_cache->save($this->result, $cache_meta, 'example');
}
$this->result["paginator"] = $this->diafan->_tpl->get('get', 'paginator', $this->result["paginator"]);
$this->result['view'] = 'show';
}
Как Вы видите по коду здесь, мы использовали кэш. Это необходимо, если Вы хотите уменьшить нагрузку на базу данных и сократить время отображения страницы.
На время разработки мы всегда рекомендуем вам отключать кэширование в параметрах сайта, потому что по умолчанию кэш сбрасывается лишь при изменении элемента в панели администрирования, то есть все Ваши манипуляции с базой данных в файле *.model.php со включенным кэшированием Вы можете увидеть не сразу.
Накидаем небольшой пример, чтобы было понятнее
Пример:
$cache_meta = array(
"name" => "trololo", // метка кеша
"language" => _LANG,
"page" => $this->diafan->page > 1 ? $this->diafan->page : 1,
"site_id" => $this->diafan->_site->id,
);
// если кэш сохранен он будет в $data если нет то выполнится условие
$data = array();
if(! $data = $this->diafan->_cache->get($cache_meta, $this->diafan->module))
{
$data = array('котейка', 'черный');
//сохранение кэша
$this->diafan->_cache->save($data, $cache_meta, $this->diafan->module);
}
Про постраничную навигацию подробнее читайте здесь.
Функции format_date()
форматирует дату в соответствии с настройкой модуля, она наследуется из
класса Model
, подробнее о ней можно почитать здесь.
Давайте добавим нашему модулю в конфигурацию кроме количества объявлений на странице еще и формат даты.
Создадим файл конфигурации modules/example/admin/example.admin.config.php и наполним его:
Пример:
public $variables = array (
'base' => array (
'nastr' => array(
'type' => 'numtext',
'name' => 'Количество объявлений на странице',
),
'format_date' => array(
'type' => 'select',
'name' => 'Формат даты',
'select' => array(
0 => '1.05.2019',
1 => '1 мая 2019 г.',
2 => '1 мая',
3 => '1 мая 2019, понедельник',
4 => 'не отображать',
),
),
)
);
public $config = array('config');
Получился функциональный модуль аж с двумя изменяемыми настройками и кэшированием.
Вы можете создать также отдельный шаблонный тег для модуля. Об этом есть отдельный урок «Как добавить шаблонный тег».
Зарегистрируйтесь или авторизируйтесь для того, чтобы оставить комментарий.