Создание простого плагина. Пошаговая инструкция для новичков. Часть 2
Это продолжение статьи для новичков о пошаговом создании простого плагина для Livestreet.
Часть 1.
7. Конфигурируем модуль
Модуль (Module) — класс, который удобно использовать как прослойку между контроллером (Экшином) и Маппером. Это удобно, если есть необходимость предварительной обработки получаемых/отправляемых данных. Так же, в Модуле удобно хранить какие-то свои функции, т.е., использовать этот класс, как библиотеку.
Откроем файл Модуля
Если вы ничего не изменяли, то класс будет пустым.
a) Создадим свойство класса $oMapper, в котором будет храниться объект Маппера:
добавим после объявления класса следующий код:
b) Создадим метод инициализации класса:
Этот метод записывает в свойство класса $oMapper созданный объект Маппера.
c) Создадим методы createBook и getBooks
8. Конфигурируем сущность (Entity)
Переходим в папку
и создаем файл класса Сущности(Entity)
Содержимое файла:
Да, это пустой класс. Без единого метода. Нам этого достаточно :-)
9. Конфигурируем маппер (Mapper)
Переходим в папку
и создаем файл класса Маппера
Содержимое файла:
Мы создали простенький Маппер для сохранения объекта Book в БД и получения всех объектов Book из БД по запросу.
10. Конфигурируем шаблон (Template)
Перейдем в папку
и создадим следующую иерархию папок:
В папке
index.tpl и books.tpl
index.tpl — отвечает за отображение данных, обработанных Экшином index, books.tpl отвечает за отображение данных, обработанных экшином books. Эти файлы автоматически подключаются движком LS при обработке соответствующих Экшинов.
Переменные, переданные из Экшина в Темплейт будут доступны через специальные теги шаблонизатора Smarty. Их можно обрабатывать и желаемым образом выводить клиенту.
Также доступны языковые переменные.
Содержание файла index.tpl:
Содержание файла index.tpl:
Структура папок и размещение файлов шаблона:
11. Конфигурируем языковой файл
Откроем языковой файл
Языковой файл состоит из именованного массива, где ключем выступает название переменной, выводимой в шаблоне, а значением — соответствующий текст.
Нам необходимо пройтись по файлам шаблона, и определить все языковые переменные.
Содержание языкового файла:
Заключение
Плагин готов. Теперь осталось проверить его работоспособность,
a) Активируем плагин.
— Для этого перейдем в админку установленных плагинов: ваш_сайт.tlt/admin/plugins/
— И активируем наш плагин найдя его в списке плагинов.
b) Проверим успешность создания таблицы плагина.
— Откроем нашу БД, например и убедимся, что таблица prefix__test_tablle была создана.
с) Перейдем на стнаницу плагина ваш_сайт_ls.tld/test и введя данные, сохраним книгу.
d) Перейдем на страницу вывода списка книг ваш_сайт_ls.tld/test/books
UPD1:
Участник сообщества PSNet указал на 2 коварные ошибки/оплошности в данной части руководства:
1. Файлы шаблонов *.tpl
Ни в коем случае не нужно добавлять комментарии в шаблонах перед подключением шаблона header.tpl:
Неправильно:
Правильно:
Перед подключением шаблона header.tpl не должно быть никаких символов, включая enter, пробел и т.п.
2. Проверка ключа LIVESTREET_SECURITY_KEY для отправляемых форм.
Это — защита от CSRF атак. Это необходимо делать всегда.
Для этого необходимо:
a) Добавить в форму скрытое поле
b) Добавить в соответствующий контроллер (Экшин) проверку формы (данная операция делается в ч.1 данной статьи):
Часть 1.
7. Конфигурируем модуль
Модуль (Module) — класс, который удобно использовать как прослойку между контроллером (Экшином) и Маппером. Это удобно, если есть необходимость предварительной обработки получаемых/отправляемых данных. Так же, в Модуле удобно хранить какие-то свои функции, т.е., использовать этот класс, как библиотеку.
Откроем файл Модуля
livestreet/plugins/test/classes/modules/test/Test.class.php
Если вы ничего не изменяли, то класс будет пустым.
a) Создадим свойство класса $oMapper, в котором будет храниться объект Маппера:
добавим после объявления класса следующий код:
protected $oMapper;
b) Создадим метод инициализации класса:
public function Init() { $this->oMapper=Engine::GetMapper(__CLASS__); }
Этот метод записывает в свойство класса $oMapper созданный объект Маппера.
c) Создадим методы createBook и getBooks
<?php class PluginTest_ModuleTest extends Module { protected $oMapper; public function Init() { $this->oMapper=Engine::GetMapper(__CLASS__); } public function createBook($post){ //Проходимся по массиву $post с данными //будущего объекта и очищаем от html-сущностей array_walk($post,function($field){ htmlspecialchars($field); }); //создаем объект сущности Book $book = Engine::GetEntity('PluginTest_ModuleTest_EntityBook'); $book->setName($post['book_name']); $book->setAuthor($post['book_author']); $book->setDescription($post['book_description']); //Объект book готов, теперь можем передать его // Мапперу и записать в базу данных if ($iId=$this->oMapper->createBook($book)) { // если сохранение в БД прошло успешно, //возвращаем ID новосозданного объекта $book->setId($iId); return $iId; } // если что-то пошло не так, возвращаем false return false; } public function getBooks() { // Просто проксируем запрос от Экшина к Мапперу if($res=$this->oMapper->getBooks()){ return $res; } return false; } } ?>
8. Конфигурируем сущность (Entity)
Переходим в папку
livestreet/plugins/test/classes/modules/test/entity
и создаем файл класса Сущности(Entity)
Book.entity.class.php
Содержимое файла:
<?php class PluginTest_ModuleTest_EntityBook extends Entity { } ?>
Да, это пустой класс. Без единого метода. Нам этого достаточно :-)
9. Конфигурируем маппер (Mapper)
Переходим в папку
livestreet/plugins/test/classes/modules/test/mapper
и создаем файл класса Маппера
Test.mapper.class.php
Содержимое файла:
<?php class PluginTest_ModuleTest_MapperTest extends Mapper { /** * Записываем в базу данных новый объект Book или обновляем существующий * @param PluginTest_ModuleTest_EntityBook $oBook * @return array|bool */ public function createBook(PluginTest_ModuleTest_EntityBook $oBook){ $sql = "INSERT INTO ".Config::Get('plugin.test.table.test_table')." ( name, author, description ) VALUES(?, ?, ?) "; if ($iId=$this->oDb->query( $sql, $oBook->getName(), $oBook->getAuthor(), $oBook->getDescription() )) { return $iId; } return false; } /** * Делаем выборку всех записей Book из таблицы * @return array */ public function getBooks(){ $sql = "SELECT * FROM ".Config::Get('plugin.test.table.test_table'); $aResult=array(); if ($aRows=$this->oDb->select($sql)) { // На основании каждой строки результата выборки создаем объект // класса Book. Это иногда удобно. Но можно и просто возвращать // именованный массив. foreach ($aRows as $aRow) { $aResult[]=Engine::GetEntity('PluginTest_ModuleTest_EntityBook',$aRow); } } return $aResult; } } ?>
Мы создали простенький Маппер для сохранения объекта Book в БД и получения всех объектов Book из БД по запросу.
10. Конфигурируем шаблон (Template)
Перейдем в папку
livestreet/plugins/page/templates
и создадим следующую иерархию папок:
В папке
ActionTestсоздадим два файла:
index.tpl и books.tpl
index.tpl — отвечает за отображение данных, обработанных Экшином index, books.tpl отвечает за отображение данных, обработанных экшином books. Эти файлы автоматически подключаются движком LS при обработке соответствующих Экшинов.
Переменные, переданные из Экшина в Темплейт будут доступны через специальные теги шаблонизатора Smarty. Их можно обрабатывать и желаемым образом выводить клиенту.
Также доступны языковые переменные.
Содержание файла index.tpl:
{include file='header.tpl'} <h1>{$aLang.plugin.test.form_title}</h1> {* Форма ввода данных книги *} <form action="" method="POST"> <input type="hidden" name="security_ls_key" value="{$LIVESTREET_SECURITY_KEY}" /> <p><label for="book_name">{$aLang.plugin.test.book_name}:</label> <input type="text" id="book_name" class="input-text input-width-full" name="book_name" value="" class="input-wide" /> </p> <p><label for="book_author">{$aLang.plugin.test.book_author}:</label> <input type="text" id="book_author" class="input-text input-width-full" name="book_author" value="" class="input-wide" /> </p> <label for="book_description">{$aLang.plugin.test.book_description}:</label> <textarea name="book_description" id="book_description" rows="20" class="input-width-full"></textarea><br /> <p> <button type="submit" class="button button-primary" name="submit_book_save">{$aLang.plugin.test.bt_save_book}</button> </p> </form> {* Парсинг массива объектов $aBooks, переданных в шаблон в Экшине. Проходимся по каждому элемну массива объектов $aBooks и выводим свойства в таблицу *} <table cellspacing="0" class="table"> <thead> <tr> <th width="180px">{$aLang.plugin.test.table_title}</th> <th align="center">{$aLang.plugin.test.table_id}</th> <th align="center">{$aLang.plugin.test.table_name}</th> <th align="center">{$aLang.plugin.test.table_author}</th> <th align="center">{$aLang.plugin.test.table_description}</th> </tr> </thead> <tbody> {foreach from=$aBooks item=oBook} <tr> <td>{$oBook->getId()}</td> <td>{$oBook->getName()}</td> <td>{$oBook->getAuthor()}</td> <td>{$oBook->getDescription()}</td> </tr> {/foreach} </tbody> </table> {* Подключаем темплейт футера *} {include file='footer.tpl'}
Содержание файла index.tpl:
{include file='header.tpl'} <h1>{$aLang.plugin.test.books_page_title}</h1> {* Парсинг массива объектов $aBooks, переданных в шаблон в Экшине. Проходимся по каждому элемну массива объектов $aBooks и выводим свойства в таблицу *} <table cellspacing="0" class="table"> <thead> <tr> <th width="180px">{$aLang.plugin.test.table_title}</th> <th align="center">{$aLang.plugin.test.table_id}</th> <th align="center">{$aLang.plugin.test.table_name}</th> <th align="center">{$aLang.plugin.test.table_author}</th> <th align="center">{$aLang.plugin.test.table_description}</th> </tr> </thead> <tbody> {foreach from=$aBooks item=oBook} <tr> <td>{$oBook->getId()}</td> <td>{$oBook->getName()}</td> <td>{$oBook->getAuthor()}</td> <td>{$oBook->getDescription()}</td> </tr> {/foreach} </tbody> </table> {* Подключаем темплейт футера *} {include file='footer.tpl'}
Структура папок и размещение файлов шаблона:
11. Конфигурируем языковой файл
Откроем языковой файл
livestreet/plugins/test/templates/language/russian.php
Языковой файл состоит из именованного массива, где ключем выступает название переменной, выводимой в шаблоне, а значением — соответствующий текст.
Нам необходимо пройтись по файлам шаблона, и определить все языковые переменные.
Содержание языкового файла:
<?php /** * Русский языковой файл плагина */ return array( 'form_title' => 'Добавление новой книги', 'book_name' => 'Название книги', 'book_author' => 'Автор', 'book_description' => 'Описание', 'bt_save_book' => 'Сохранить книгу', 'table_title' => 'Список книг', 'table_name' => 'Название', 'table_author' => 'Автор', 'table_description' => 'Описание', 'books_page_title' => 'Список сохраненных книг', ); ?>
Заключение
Плагин готов. Теперь осталось проверить его работоспособность,
a) Активируем плагин.
— Для этого перейдем в админку установленных плагинов: ваш_сайт.tlt/admin/plugins/
— И активируем наш плагин найдя его в списке плагинов.
b) Проверим успешность создания таблицы плагина.
— Откроем нашу БД, например и убедимся, что таблица prefix__test_tablle была создана.
с) Перейдем на стнаницу плагина ваш_сайт_ls.tld/test и введя данные, сохраним книгу.
d) Перейдем на страницу вывода списка книг ваш_сайт_ls.tld/test/books
UPD1:
Участник сообщества PSNet указал на 2 коварные ошибки/оплошности в данной части руководства:
1. Файлы шаблонов *.tpl
Ни в коем случае не нужно добавлять комментарии в шаблонах перед подключением шаблона header.tpl:
Неправильно:
{* какой-то комментарий *} {include file='header.tpl'}
Правильно:
{include file='header.tpl'}
Перед подключением шаблона header.tpl не должно быть никаких символов, включая enter, пробел и т.п.
2. Проверка ключа LIVESTREET_SECURITY_KEY для отправляемых форм.
Это — защита от CSRF атак. Это необходимо делать всегда.
Для этого необходимо:
a) Добавить в форму скрытое поле
<input type="hidden" name="security_ls_key" value="{$LIVESTREET_SECURITY_KEY}" />
b) Добавить в соответствующий контроллер (Экшин) проверку формы (данная операция делается в ч.1 данной статьи):
$this->Security_ValidateSendForm();
14 комментариев
перед подключением хедера не должно быть комментариев, т.к. переводы строк попадают перед доктайпом чего делать нельзя
добавьте в экшен при добавлении формы проверку ключа
security_ls_key
и напишите что так нужно делать всегдаПро ключ — тоже согласен.
Отредактирую утром уже. Большое спасибо за уточнения!
Fatal error: Call to a member function getId() on a non-object in D:\*****\dc39eca987ad1eaac2deab28163c98ce210d1a65.file.books.tpl.php on line 55
Спасибо автору за труд — отличная статья!
Web Sitemiz: gunlukdairem.com
İyi günler dileriz.