Создание модуля для Dolphin 7 . Урок первый.
В данной статье я расскажу вам основы создания своих собственных модулей для дельфина седьмой версии. Мы не будем создавать слишком сложный модуль, будет достаточно просто - ссылка в навигационном меню, собственная главная страничка, блок на странице профиля, к-либо данные в БД. Для начала думаю достаточно.
Итак, для начала нам нужно:
Установленный дельфин (естественно)
Знания программирования на PHP/mySQL и др тоже не повредят
Желание
Шаг1: скачивание пакета
Для начала давайте скачаем демо-модуль для дальнейшего изучения. Данную папку разархивируйте, и скопируйте (закачайте) в вашу папку 'modules' на хостинге.
Шаг2: структура проекта
Итак поехали. Для начала покажу структуру файлов-папок проекта
modules/andrey/appl1/classes/ - папка содержащая классы проекта
modules/andrey/appl1/classes/Appl1Config.php - конфиг-класс
modules/andrey/appl1/classes/Appl1Db.php - класс базы данных
modules/andrey/appl1/classes/Appl1Module.php - основной класс проекта
modules/andrey/appl1/classes/Appl1Template.php - класс шаблона
modules/andrey/appl1/install/ - установочная папка
modules/andrey/appl1/install/config.php - конфиг файл
modules/andrey/appl1/install/info/ - папка с html файлами которые можно отображать в процессе установки
modules/andrey/appl1/install/info/inst_concl.html - заключение после установки
modules/andrey/appl1/install/info/inst_intro.html - введение перед установкой
modules/andrey/appl1/install/info/uninst_concl.html - заключение после удаления
modules/andrey/appl1/install/info/uninst_intro.html - введение перед удалением
modules/andrey/appl1/install/installer.php - класс установочник
modules/andrey/appl1/install/langs/ - папка с языками
modules/andrey/appl1/install/langs/en.php - файл английского языка
modules/andrey/appl1/install/langs/ru.php - файл русского языка
modules/andrey/appl1/install/sql/ - установочная папка с SQL файлами
modules/andrey/appl1/install/sql/install.sql - установочный SQL
modules/andrey/appl1/install/sql/uninstall.sql - SQL удаления (очистка данных)
modules/andrey/appl1/request.php - файл перенаправляющий все запросы на наш главный класс
modules/andrey/appl1/templates/base/ - папка базового шаблона
modules/andrey/appl1/templates/base/home_page.html - шаблон который мы будем использовать для главной странички
modules/andrey/appl1/templates/base/profile_page.html - шаблон для страницы профиля в наш блок
Здесь - andrey, всего лишь имя поставщика (создателя) например, appl1 - как имя проекта, еслественно тут могут быть ваши значения. Единственное - местоположения файлов должно быть идиентичным, соблюдая данную иерархию. Т.к. допустим инсталлятор дельфина будет искать папку install а в ней конфиг файл для того чтобы работать с ним и отобразить в админке на странице установки/удаления модулей. Так что, будьте внимательны с путями.
Шаг3: начинаем изучать внутренности файлов проекта
Для начала рекомендую начать именно с конфигов и папки установки чтобы знать что мы делаем
install/config.php
Постарался везде вставить комментарии чтобы было все понятно, вообщем - изучайте
<?php
$aConfig = array(
/**
* Основная секция.
*/
'title' => 'My new application #1', /* просто название модуля, видно в админке */
'version' => '1.1.0', /* версия модуля */
'vendor' => 'Andrey', /* Поставщик, Продавец, вообщем ваше имя */
'update_url' => '', /* путь к обновлению модуля */
'compatible_with' => array( /* совместимость модуля */
'7.0.5', '7.0.6'
),
/**
* 'home_dir' и 'home_uri' - должны быть уникальными. Не используйте пробелы в 'home_uri' и другие специальные символы.
*/
'home_dir' => 'andrey/appl1/', /* директория модуля от папки 'modules', вы можете иметь своё собственное имя */
'home_uri' => 'appl1', /* URI модуля (будет использоваться в ссылках к модулю) */
'db_prefix' => 'a_appl1', /* префикс к вашим таблицам для БД */
'class_prefix' => 'Appl1', /* префикс классов нашего модуля */
/**
* Секция установки/удаления.
*/
'install' => array(
'show_introduction' => 1, /* показывать введение при установке модуля */
'change_permissions' => 0, /* изменять ли разрешения */
'execute_sql' => 1, /* выполнить SQL */
'update_languages' => 1, /* компилировать кеши языков */
'recompile_global_paramaters' => 0, /* компиляция глобальных параметров */
'recompile_main_menu' => 1, /* компиляция кеша навигационного меню */
'recompile_member_menu' => 0, /* компиляция кеша пользовательского меню */
'recompile_site_stats' => 0, /* компиляция кеша статистики сайта */
'recompile_page_builder' => 1, /* компиляция кеша блоков страниц */
'recompile_profile_fields' => 0, /* компиляция кеша полей профиля */
'recompile_comments' => 0, /* компиляция кеша комментариев */
'recompile_member_actions' => 0, /* компиляция кеша действий пользователей */
'recompile_tags' => 0, /* компиляция кеша тегов */
'recompile_votes' => 0, /* компиляция кеша голосований */
'recompile_categories' => 0, /* компиляция кеша категорий */
'recompile_search' => 0, /* компиляция кеша поиска */
'recompile_injections' => 0, /* компиляция кеша инъекций */
'recompile_permalinks' => 0, /* компиляция кеша пермалинок */
'recompile_alerts' => 0, /* компиляция кеша алертов */
'clear_db_cache' => 0, /* очистка кеша БД */
'show_conclusion' => 1 /* отображение заключения после установки модуля */
),
'uninstall' => array (
'show_introduction' => 1,
'change_permissions' => 0,
'execute_sql' => 1,
'update_languages' => 1,
'recompile_global_paramaters' => 0,
'recompile_main_menu' => 1,
'recompile_member_menu' => 0,
'recompile_site_stats' => 0,
'recompile_page_builder' => 1,
'recompile_profile_fields' => 0,
'recompile_comments' => 0,
'recompile_member_actions' => 0,
'recompile_tags' => 0,
'recompile_votes' => 0,
'recompile_categories' => 0,
'recompile_search' => 0,
'recompile_injections' => 0,
'recompile_permalinks' => 0,
'recompile_alerts' => 0,
'clear_db_cache' => 0,
'show_conclusion' => 1
),
/**
* Секция зависимостей
*/
'dependencies' => array(
// пример (означает наш модуль будет зависеть от наличия модуля бунекс фоток
/*'photos' => 'BoonEx Photos Module',*/
),
/**
* Категория языковых ключей
*/
'language_category' => 'My new application #1',
/**
* Секция специальных разрешений
*/
'install_permissions' => array(
// пример, - при установке модуля будет проверяться наличие разрешение на запись в папку 'data'
/*'writable' => array('data')*/
),
'uninstall_permissions' => array(),
/**
* Секция введения и заключения (текстовые описания).
*/
'install_info' => array(
'introduction' => 'inst_intro.html',
'conclusion' => 'inst_concl.html'
),
'uninstall_info' => array(
'introduction' => 'uninst_intro.html',
'conclusion' => 'uninst_concl.html'
)
);
?>
install/installer.php
<?php
/***************************************************************************
*
* Класс Инсталлера (обычно редко подвергается изменениям
*
***************************************************************************/
bx_import('BxDolInstaller');
class Appl1Installer extends BxDolInstaller {
function Appl1Installer($aConfig) {
parent::BxDolInstaller($aConfig);
}
}
?>
файлы папки install/info/ : inst_concl.html, inst_intro.html, uninst_concl.html и uninst_intro.html
особого смысла нету публиковать тут, обычные текстовые файлы, вы сами сможете изучить их содержимое в нашем пакете
файлы папки install/langs/ : en.php и ru.php
Аналогично, представляют собой PHP массив с информацией о языковых ключах используемых в модуле
install/sql/install.sql
Установочный SQL файл, содержащий:
-- таблицы
CREATE TABLE IF NOT EXISTS `[db_prefix]_posts` (
`id` int(10) unsigned NOT NULL auto_increment,
`title` varchar(255) default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `[db_prefix]_posts` (`id`, `title`) VALUES
(NULL, 'запись один'),
(NULL, 'запись два'),
(NULL, 'запись три'),
(NULL, 'запись четыре'),
(NULL, 'запись пять');
-- навигационное меню - добавим ссылку
SET @iTopMenuLastOrder := (SELECT `Order` + 1 FROM `sys_menu_top` WHERE `Parent` = 0 ORDER BY `Order` DESC LIMIT 1);
INSERT INTO `sys_menu_top` (`ID`, `Parent`, `Name`, `Caption`, `Link`, `Order`, `Visible`, `Target`, `Onclick`, `Check`, `Editable`, `Deletable`, `Active`, `Type`, `Picture`, `BQuickLink`, `Statistics`) VALUES
(NULL, 0, 'MyNewAppl', '_appl1_main', 'm/appl1/home', @iTopMenuLastOrder, 'non,memb', '', '', '', 1, 1, 1, 'top', '', 1, '');
-- блок на страницу профиля
INSERT INTO `sys_page_compose` (`ID`, `Page`, `PageWidth`, `Desc`, `Caption`, `Column`, `Order`, `Func`, `Content`, `DesignBox`, `ColWidth`, `Visible`, `MinWidth`) VALUES
(NULL, 'profile', '998px', 'MyNewAppl', '_appl1_main', 1, 0, 'PHP', 'return BxDolService::call(''appl1'', ''profile_page'', array($this->oProfileGen->_iProfileID));', 1, 34, 'non,memb', 0);
Как видим, тут есть инструкции по созданию таблицы в БД с тестовыми записями, ссылку в меню, блок.
install/sql/uninstall.sql
SQL содержащий инструкции по удалению модуля (надо же почистить все за собой после того как модуль удалим), содержащий:
-- таблицы
DROP TABLE IF EXISTS `[db_prefix]_albums`;
-- навигационное меню - удаляем ссылку (топ и все в подменю заодно)
SET @iCatRoot := (SELECT `ID` FROM `sys_menu_top` WHERE `Name` = 'MyNewAppl' LIMIT 1);
DELETE FROM `sys_menu_top` WHERE `Parent` = @iCatRoot;
DELETE FROM `sys_menu_top` WHERE `ID` = @iCatRoot;
-- блок на страницу профиля
DELETE FROM `sys_page_compose` WHERE `Desc` = 'MyNewAppl';
request.php
<?
require_once(BX_DIRECTORY_PATH_INC . 'profiles.inc.php');
check_logged();
require_once(BX_DIRECTORY_PATH_CLASSES . 'BxDolRequest.php');
BxDolRequest::processAsAction($GLOBALS['aModule'], $GLOBALS['aRequest']);
?>
Данный файл очень редко подвергается изменениям, особого смысла нет, служит для перенаправления всех запросов на модуль - основному классу. Вообщем - берите как есть.
classes/Appl1Config.php
<?php
/***************************************************************************
*
* Конфиг класс, может использоваться для ваших нужд (допустим для хранения настроек модуля)
*
***************************************************************************/
bx_import('BxDolConfig');
class Appl1Config extends BxDolConfig {
/**
* Конструктор
*/
function Appl1Config($aModule) {
parent::BxDolConfig($aModule);
}
}
?>
classes/Appl1Db.php
<?php
/***************************************************************************
*
* Класс Базы данных, содержит все функции обращений к БД
*
***************************************************************************/
bx_import('BxDolModuleDb');
class Appl1Db extends BxDolModuleDb {
var $_oConfig;
/*
* Конструктор
*/
function Appl1Db(&$oConfig) {
parent::BxDolModuleDb($oConfig);
$this->_oConfig = &$oConfig;
}
/*
* Функция - пример: получение из БД из нашей таблицы 5 последних записей
*/
function getPosts($iAmount = 5) {
return $this->getAll("SELECT * FROM `a_appl1_posts` ORDER BY `id` LIMIT {$iAmount}");
}
}
?>
classes/Appl1Module.php
<?php
/***************************************************************************
*
* Основной класс, содержит весь необходимый для работы функционал
*
***************************************************************************/
bx_import('BxDolModule'); // данная функция является неким аналогом require_once
class Appl1Module extends BxDolModule {
/*
* Переменные
*/
var $aPageTmpl; /* объект темплейта */
var $sHomeUrl; /* данный путь будет содержать нечто типа http://..../modules/andrey/appl1/ - возможно вам понадобится */
var $sHomePath; /* данный путь содержит путь к папке с вашим модулем (для своих нужд) */
var $sModuleUrl; /* данный путь содержит Урл к модулю: http://...../m/appl1/ */
var $_iVisitorID; /* ID посетителя, 0 если не залогинен */
/*
* Конструктор
*/
function Appl1Module($aModule) {
parent::BxDolModule($aModule);
$this->aPageTmpl = array( // инициализируем, допустим 99 страница, дефолт тайтл страницы - тайтл сайта
'name_index' => 99,
'header' => $GLOBALS['site']['title'],
'header_text' => '',
);
$this->sHomeUrl = $this->_oConfig->getHomeUrl();
$this->sHomePath = $this->_oConfig->getHomePath();
$this->sModuleUrl = BX_DOL_URL_ROOT . $this->_oConfig->getBaseUri();
$this->_iVisitorID = $this->getUserId();
}
// обратите внимание - данная функция будет вызываться при обращении к m/appl1/home или к m/appl1/
function actionHome() {
$aVariables = array (
);
// следующей функцией мы берем шаблон 'home_page.html' и её код в переменную заносим
$sCode = $this->_oTemplate->parseHtmlByName('home_page.html', $aVariables);
$sCode2 = '';
$aPosts = $this->_oDb->getPosts();
foreach ($aPosts as $i => $aPostInfo) {
$sCode2 .= '<div>' . $aPostInfo['title'] . '</div>';
}
$this->aPageTmpl['header'] = _t('_appl1_main'); // выставляем заголовки
$this->aPageTmpl['header_text'] = _t('_appl1_main');
// вывод в основной шаблон
$this->_oTemplate->pageCode($this->aPageTmpl, array('page_main_code' => $sCode . $sCode2));
}
// сервис функция - вызов сервиса модуля 'profile_block' -> serviceProfilePage
function serviceProfilePage($iProfileID) {
$aVariables = array (
'nickname' => getNickname($iProfileID),
);
// отдаем результат, заменив ключ nickname на значение - имя профиля данной страницы
return $this->_oTemplate->parseHtmlByName('profile_page.html', $aVariables);
}
}
?>
classes/Appl1Template.php
<?php
/***************************************************************************
*
* Класс шаблона, обычно может содержать разные функции по работе с шаблоном
*
***************************************************************************/
bx_import('BxDolModuleTemplate');
class Appl1Template extends BxDolModuleTemplate {
/*
* Конструктор
*/
function Appl1Template(&$oConfig, &$oDb) {
parent::BxDolModuleTemplate($oConfig, $oDb);
}
/*
* Данную функцию будет использовать для вывода данных
*/
function pageCode ($aPage = array(), $aPageCont = array(), $aCss = array(), $aJs = array(), $bAdminMode = false, $isSubActions = true) {
if (!empty($aPage)) {
foreach ($aPage as $sKey => $sValue)
$GLOBALS['_page'][$sKey] = $sValue;
}
if (!empty($aPageCont)) {
foreach ($aPageCont as $sKey => $sValue)
$GLOBALS['_page_cont'][$aPage['name_index']][$sKey] = $sValue;
}
if (!empty($aCss))
$this->addCss($aCss);
if (!empty($aJs))
$this->addJs($aJs);
if (!$bAdminMode)
PageCode($this);
else
PageCodeAdmin();
}
}
?>
Вот, этим мы закончили обзор все классов проекта, очередь за малым - я подготовил пару шаблон-файлов
templates/base/home_page.html
<h3>Данную страницу мы можем наблюдать зайдя по ссылке (в меню например) m/appl1/home или m/appl1/</h3>
<h3><bx_text:_appl1_about /></h3>
templates/base/profile_page.html
<h2>Привет, мое имя __nickname__</h2>
<h3>Данный блок мы видим на странице профиля</h3>
Обратите внимание, я использую ключ __nickname__ в шаблоне. Также, еще один - bx_text, данные ключ-функция преобразует указанный языковой ключ в его строковое значение
Надеюсь большинство кода получилось более менее понятным, я старался ставить комментарии везде чтобы было ясно что я делал. Если у вас имеются вопросы или другие предложения - не стесняйтесь писать нам.