Наверх

Как создать свой модуль

В данном разделе документации рассказано как создать модуль для 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 предоставляет огромные возможности для расширения функционала административной части модуля, все зависит от вашей фантазии и правильного крепления рук к телу.

Еще есть замечательный тип в $variablesmodule. Он означает, что необходимо подключить к редактированию сторонний модуль.

Как это работает.

Там где нужно подключить модуль 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.2014',
                
1 => '1 мая 2014 г.',
                
2 => '1 мая',
                
3 => '1 мая 2014, понедельник',
                
4 => 'не отображать',
            ),
        ),
     )
);

public
$config = array('config');

Получился функциональный модуль аж с двумя изменяемыми настройками и кэшированием.

Вы можете создать также отдельный шаблонный тег для модуля. Об этом есть отдельный урок «Как добавить шаблонный тег».

Исходный код модуля example.

Ваши комментарии и дополнения

как создать модуль?
Роман, с чем конкретно у Вас возникают проблемы?
Просто не понял как подступиться, начало этого документа бы дополнить, что нужно в папке modules создать свою папку name, а уже в ней создавать name.install.php. А то я грешным делом подумал, что уже существует некий файл example.install.php, в котором описаны все модули, но его почему-от не нашел в дебрях CMS :) А так в принципе разобрался, модуль создал, спасибо:)
Здравствуйте! Что-то пошло не так. Я создал модуль по инструкции выше. Скачал "каркас" - ничего не меняя залил в проект, модуль прикрепил. Почти все работает (добавляет в базу - mysql новости, удаляет, редактирует, да и в админке все прекрасно работает). Но не работает пользовательская часть. На страничке просто не отображается то, что я задаю в админке. Блок "example-text" добавляется, но он пустой. Ошибка (Undefined index: text). Складывается впечатление что запрос ничего не вернул, либо $result['text'] вообще не видно из модуля "example.view.show". Помогите, пожалуйста. Я совсем поплыл с этим модулем
Это всего лишь каркас. Не готовый модуль. Мы не предполагали, что кто-то будет его использовать в готовом виде. Если надо готовый модуль, то возьмите уже реализованный в DIAFAN.CMS, например, модуль Новости. И подгоните его под свои нужды.

Если Вы взялись за реализацию модуля, значит Вы хотя бы немного разбираетесь в PHP. Смотрите в моделе собираются данные, которые будут переданы в шаблон. В примере они записываются в переменную $this->result['rows']. Это массив с записями.
В шаблоне нужно именно эту переменную использовать. То есть надо цикл по массиву
Код
foreach($result["rows"] as $row){...}

и выводить данные уже в нужном Вам виде.
Спасибо! Все логично.
Не заметил. Мне даже стыдно было с этим не разобраться
Не работает пагинация по данному примеру.
Странички внизу вывелись, вроде разбивает правильно, но при клике на номер странички выскакивает ошибка 404 - страница не найдена. Прочитал уже документацию вдоль и поперек. Найти причину не получается.
Задайте количество элементов на странице:

Код
$this->diafan->_paginator->nastr = 10;


и с контроллере должно быть:
Код

$this->rewrite_variable_names = array('page');


Смотрите, например, модуль search.
При добавлении в админке вылазиет ошибка
Unknown column 'name1' in 'field list'
У меня нету такого поля - но оно постоянно просит name1

Добавил поле name1 стала вылезать ошибка
Unknown column 'name11' in 'field list'
Чё за ерунда у вас с Cms - как с ней работать?

Так в принципе с любым названием переименовал на title теперь пишет
Unknown column 'title1' in 'field list'
Дурдом какой то - и поиск ничего не дал
Поле name1, name2 и т.д. - мультиязычные поля поля name, обращаться к нему нужно в квадратных скобках [name], а номер языка запрос добавит автоматически, исходя из того, в каком языке мы находимся.
Работать с CMS, особенно начинать программировать, нужно не наскоком, а вдумчиво, читая документацию с начала, и задавая предметные вопросы в службу поддержки.
У вас в данном туториале ошибка.
Вы не сказали ничего про $variables_list
Поэтому у меня и список не выводился на странице модуля через метод show
$variables_list появилось в 6.0. В ближайшее время мы обновим документацию и добавим описание новых настроек интерфейса.
Марина, а не планируется вебинар как создать свой модуль, на движке 6.0. ? Это было бы просто отлично, у Вас получается объяснить все просто и доходчиво.
Спасибо! Пока не обсуждали новые вебинары. Но думаю, что изменения в 6.0 вполне полноценная и интересная тема для вебинара. Подниму тему на очередной планерке.
Никак не могу разобраться. Если в 6ке распаковать и загрузить example то в админке когда нажимаешь кнопку Добавить объявление на странице добавления нового объявления есть блок который должен выводить текущего пользователя (как автора) и давать возможность его изменить. В примере в этом месте отображается "Нажми ЗДЕСЬ"
можно этот момент до иллюстрировать до конца?
Спасибо.
>В примере в этом месте отображается "Нажми ЗДЕСЬ"

Отображается, так как в примере написана функция edit_variable_user_id(). Смотрите ее описание выше. Если бы ее не было подключилась бы одноименная функция из глобального файла edit_functions.php. Она как раз дает возможность посмотреть текущего пользователя и возможность его изменить.
Цитата
Теперь модуль появится в списке модулей для установки в разделе «Модули и БД» – «Установка модулей». Устанавливаем модуль.

А что делать, если новый модуль там не появляется?
Зарегистрируйтесь или авторизируйтесь для того, чтобы оставить комментарий.