Zippy – компонентный событийно- ориентированный фреймворк на PHP, предназначенный для быстрой разработки сайтов. Zippy легок для изучения, обеспечивает полное отделение дизайна от логики, а также отделение бизнес-логики от функций обеспечения жизненного цикла и состояния элементов страницы.
Главная идея – предоставить разработчику необходимый набор компонентов, который позволит
сосредоточиться на разработке бизнес-логики сайта.
Разработчику нет необходимости работать с запросами, роутерами,
многочисленными API - он работает только с событиями и свойствами серверных компонентов.
Обмен данными с браузером, рендеринг шаблона страницы, обработка
запросов и т.д. обеспечивается компонентами, соответствующими клиентским элементам страницы. То есть если вы
кликнули
на странице по ссылке или кнопке, все что вам нужно - это назначить
на серверной стороне обработчик данного события для данного компонента (компонент - это просто PHP класс) и написать
в нем
код бизнес-логики.
Обмен данными с компонентами производится через свойства этих компонентов -
если, например, вам нужно вывести выпадающий список, вы просто передаете компоненту ассоциативный массив.
Компонентная структура Zippy позволяет легко разделять работу между разработчиками, расширять и создавать новые компоненты и модули. Наиболее эффективное применение фреймворка – интерактивные сайты, предполагающие взаимодействие с пользователями аналогично десктопным приложениям (так называемый rich-интерфейс).
Основные архитектурные решения по разделению логики и представления заимствованы с фреймворка Wicket (в некотором смысле можно рассматривать как портинг на PHP), а также (прямо или косвенно) ряд идей с таких решений как: JSF, ASP.NET, Delphi for PHP и подобных компонентно-ориентированных систем.
Установка фреймворка производится с помощью Composer.
composer require leon-mbs/zippy
В заголовке страницы указать
<link rel="stylesheet" href="/vendor/leon-mbs/zippy/assets/css/bootstrap.css">
<link rel="stylesheet" href="/vendor/leon-mbs/zippy/assets/css/zippy-bundle.min.css">
<script src="/vendor/leon-mbs/zippy/assets/js/jquery.js" type="text/javascript">
<script src="/vendor/leon-mbs/zippy/assets/js/bootstrap.bundle.js" type="text/javascript">
<script src="/vendor/leon-mbs/zippy/assets/js/zippy-bundle.min.js" type="text/javascript">
Эти файлы включают необходимые фронт-энд библиотеки - JQuery, Twitter Bootstrap, Awesome font и все
необходимые плагины и компоненты.
Кроме того, можно скачать фреймворк в сборе
со всеми необходимыми библиотеками в виде архива.
Репозиторий фреймворка на GitHub: Ссылка
Документация по классам фреймворка
Вместе с фреймворком в папке demo идет демо приложение с примерами. Это приложение можно использовать как стартовое
(заготовку).
Нужно только заменить страницы с примерами на свои. Перед началом работы разумеется необходимо выполнить Сomposer.
Можно также скачать демо-приложение в сборе с
фреймворком.
Также можно смотреть исходники проектов,
где можно найти примеры организации работы с БД, подключение авторизации и пр.
Основным элементом сайта, построенного с использованием Zippy, является страница.
Страница состоит из PHP класса - наследника от класса WebPage
(бэкенд) и HTML файла (фронтэнд).
Для каждого элемента (HTML тэга) страницы, связанного с бизнес-логикой, создается экземпляр
соответствующего класса (Zippy-компонент) в PHP коде.
<body>
<span zippy="msg"></span>
<a zippy="onmsg">Клик</a>
</body>
use \Zippy\Html\Label;
use \Zippy\Html\Link\ClickLink;
class Example1 extends \Zippy\Html\WebPage
{
//В конструкторе создаем экземпляры компонентов
public function __construct($params = null) {
$this->add(new Label('msg'));
$this->add(new ClickLink('onmsg', $this, 'OnClick'));
}
// Обработчик клика по ссылке
public function OnClick($sender) {
//Присваиваем текст для вывода в тэге span
$this->msg->setText("OK");
}
}
Компонент обеспечивает рендеринг в HTML, сохранение состояния
(в том числе для элементов ввода), а также вызов обработчиков событий,
возникающих при навигации пользователя по странице. Связь между компонентом
и HTML представлением обеспечивается с помощью атрибута "zippy"
в
соответствующих HTML тэгах. При создании экземпляра компонента в его
конструктор передается значение атрибута "zippy"
, которое присваивается полю
id
, определенному в классе HtmlComponent
, от которого наследуются все компоненты.
Таким образом HTML код не включает в себя никаких скриплетов и прочих чужеродных
вставок. При рендеринге компонент, манипулируя тегом, изменяет его значение и/или
значение его атрибутов, отображая таким образом свои данные в выходном HTML потоке.
Важное условие - иерархия компонентов страницы строго соответствует вложенности соответствующих
(с атрибутом "zippy"
) HTML тэгов. Если, например, ссылка или другой элемент находится в форме и
для формы как и для элемента необходимо создать соответствующий серверный компонент, то компонент
ссылки должен быть добавлен к форме вызовом метода Add
предварительно созданного объекта формы.
<body>
<form zippy="form1">
<input type="text" zippy="message" >
</form>
</body>
public function __construct($params = null) {
$this->add(new Form('form1'));
$this->form1->add(new TextInput('message');
}
use \Zippy\Html\Label;
use \Zippy\Html\Link\ClickLink;
class Example1 extends \Zippy\Html\WebPage
{
public $counter=0;
// Обработчик клика по ссылке
public function OnClick($sender) {
//Присваиваем текст для вывода в тэге span
$this->counter++;
$this->msg->setText("Счетчик ". $this->counter);
}
}
Таким образом может быть сохранена между обновлениями страницы любая сложная структура.
Естественно, если нужно очистить данные в компоненте, нужно делать это явно аналогично десктопным приложениям.
$this->msg->setText("");
WebApplication
в зависимости от анализа запросов браузера к серверу.
При первом открытии страницы приложение создает экземпляр класса страницы. В конструкторе
страницы создаются экземпляры всех компонентов страницы, выполняется биндинг и назначение обработчиков
событий. Затем экземпляр класса страницы сериализуется со всем содержимым и записывается в сессионное
хранилище. После этого приложение загружает HTML шаблон с места на диске, указанного разработчиком в
функции getTemplate
, парсит его и вызывает метод рендеринга класса страницы. Класс страницы
рендерит все дочерние компоненты. Компонент изменяет соответствующий ему (связанный через атрибут
zippy
)
HTML тэг, корректируя его содержание и/или атрибуты. После рендеринга страницы приложение отправляет
измененный HTML код браузеру.
При запросе со страницы (например, клик по ссылке) приложение десериализует экземпляр класса страницы из сессии и находит компонент - инициатор запроса (ссылка, кнопка и т.д.). Компонент активизирует связанную с ней пользовательскую функцию – обработчик события, которым обычно является метод класса страницы, поскольку это позволяет иметь доступ ко всем компонентам страницы и таким образом реализовать всю бизнес-логику, связанную с поведением страницы, обменом данных и т.д. Затем экземпляр страницы вместе с экземплярами всех компонентов (хранящих текущее состояние данных) сохраняется в сессионном хранилище, выполняется рендеринг и отправка ответа в браузер. Сессионное хранилище сохраняет историю изменения страниц, что позволяет отдавать страницу с соответствующим "историческим" состоянием при навигации браузера кнопками "вперед"/"назад".
Класс приложения. Выполняет разбор HTTP запроса, управляет жизненным циклом страницы
и формирует ответ для клиента. Для использования создать экземпляр класса наследнинка от WebApplication
и
переопределить минимум одну функцию загрузки шаблонов страниц getTemplate
.
Входным параметром является имя класса страницы, выходным - содержание
шаблона. Пример реализации можно посмотреть в демо приложеиии.
Управляя загрузкой шаблона можно легко реализовать сменяемые темы сайта.
В сложных проектах функцию обработки (или несколько функций, если модульное приложение) можно установить методом
setTemplate
и может задаватся строковым именем
или лямбдой. В этом случае можно не создавать свой экзеспляр приложения, а использовать непосредственно
WebApplication
.
При создании экземпляра WebApplication
или собственного класса-наследника в
конструктор необходимо передать имя класса начальной
страницы сайта. Пример кода из index.php:
class Application extends \Zippy\WebApplication
{
public function getTemplate($name)
{
//загрузка шаблонов для страниц
$name = str_replace("Pages\\", "", ltrim($name, '\\'));
$path = __DIR__ . '/' ."templates/" . strtolower($name) . ".html";
$template = file_get_contents($path);
if ($template == false) {
new \Exception('Неверный путь к шаблону страницы: ' . $path);
}
return $template;
}
// если требуется роутинг
public function Route($uri){
if($uri == '') $uri = 'page1';
$uria= explode("/",$uri);
if($pages[$uria[0]]=='page1'){
$this->LoadPage("\\Pages\\Page1");
}
else if ($pages[$uria[0]]=='page2'){
$this->LoadPage("\\Pages\\Page2",$uria[1]); //страница с параметром
}
else {
$this->getResponse()->to404Page() ;
}
}
}
// создаем экземпляр приложения с параметром класса главной страницы сайта
$app = new Application('Pages\Main');
$app->Run();
Класс страницы. Для создания класса необходимо расширить абстрактный класс WebPage
.
В конструкторе создаются все компоненты страницы. Иерархия компонентов должна строго
соответствовать вложенности тэгов с атрибутом zippy
в шаблоне. Как правило, в классе
страницы создаются функции обработчиков событий, а также реализуется логика работы
страницы. Экземпляры компонентов страницы создаются один раз при первом обращении к
странице. Отслеживать жизненный цикл страницы можно переопределив методы
beforeRequestHandle()
, afterRequestHandle()
и пр.
Приинцип работы класса страницы напомнинает класс бекенда в ASP WebForms или
десктопных Delphi/WinForms - экземпляр класса страницы (формы) содержит остальные элементы как контейнер,
управляет их жизненным циклом. Обработчики
событий элементов являются методами класса страницы.
Базовый класс для всех компонентов. Каждый компонент имеет уникальный в пределах страницы номер
элемента (поле id
) , соответствующий аттрибуту zippy
из соответствующего тэга HTML
шаблона.
Каждый компонент, расширяющий базовый класс, должен реализовать метод RenderImpl()
, который отвечает
за рендеринг (прорисовку) компонента на странице путем изменения HTML тэга, связанного с данным
компонентом. Свойство attributes
позволяет управлять атрибутами HTML тэга. Содержимое тэга задается
классами-потомками HtmlComponent
в зависимости от его типа.
Базовый класс контейнера для компонентов. Контейнерами являются: класс страницы, класс HTML формы,
панели (обычно тэг DIV
) и прочие компоненты которые могут содержать в себе другие объекты типа
HtmlComponent
(то
есть HTML
тэги, которые могут содержать вложенные тэги). Сам HtmlContainer
также является наследником от HtmlComponent
. В классе перегружены
методы __set()
и __get()
, поэтому
к вложенным компонентам можно обращаться, используя динамическое свойство, совпадающее с ID
компонента.
Например:
<form zippy="form1">
<input type="text" zippy="username">
</form>
$form = new Form();
$form = add(new TextInput('username'));
...
$form->username->getText();
Label
Служит для вывода
текстовых данных
на странице. Как правило отображается с
помощью тэга SPAN
, но можно использовать TD
, DIV
и прочие, которые могут
иметь
текстовое содержимое внутри тега.
Panel
используется как
контейнер, когда
надо временно скрыть группу элементов.
Например, при редактировании строки таблицы скрыть таблицу и показать форму редактирования.
Поскольку работа происходит в пределах той же страницы, сохраняются все сортировки, фильтрация и пагинация таблицы.
Как правило, компонент отображается с помощью тэга div
или другого блочного элемента.
Фреймворк содержит несколько разновидностей компонентов для HTML ссылок. Все они привязываются к тэгу <a> шаблона. Наиболее используемые:
ClickLink
-
служит для
вызова обработчика события в классе cтраницы без возможности
сделать закладку в браузере (поскольку это не имеет смысла - ссылка не ведет на какой-либо
ресурс, а просто вызывает обработчик).
public function __construct($params = null) {
$this->add(new ClickLink('onmsg'))->onClick( $this, 'OnClick');
}
// Обработчик
public function OnClick($sender) {
}
}
BookmarkableLink
-
используется для внешнего перехода или ЧПУ с возможностью создать закладку.
Для указания адреса страницы указывается имя класса страницы с прямыми слешами
RedirectLink
-
используется для редиректа на другую страницу. Имя класса страницы задается как параметр
в конструкторе.
SubmitLink
-
отправляет
форму на сервер, c возможностью вызвать обработчик события по отправке формы.
Компоненты соответствуют тегам элементов ввода HTML формы. Для принятия данных по отправке формы компоненты
реализуют метод
getRequestData()
, в котором считывают «свои» данные с $_POST
или $_GET
переменных. При рендеринге как и другие визуальные
компоненты форматируют тэги в соответствии со своими значениями. Если значения не были изменены,
отображаются данные, что были при вводе формы. Таким образом автоматически сохраняется состояние
всех элементов формы - полей ввода, переключателей и т.д при перезагрузке страницы.
Для реакции на отправку формы, форме назначается обработчик.
public function __construct($params = null) {
$this->add(new Form('form1'))->onSubmit( $this, 'OnForm1');
}
// Обработчик
public function OnForm1($sender) {
}
Вместо формы обработчик может быть назначен одному или нескольким
компонентам типа SubmitLink
или
SubmitButton
,
которые могут
отправлять форму.
Компонент должен быть внутри формы.
public function __construct($params = null) {
$this->add(new Form('form1'))->onSubmit( $this, 'OnForm1');
$this->form1->add(new SubmitLink('sl1'))->onClick( $this, 'OnForm1');
}
// Обработчик
public function OnForm1($sender) {
}
Для взаимодействия между собой компонентов, существует набор интерфейсов, которые должен реализовать тот или иной компонент. Наиболее используемые:
Requestable
– компонент
способен обрабатывать HTTP запрос.ClickListener
–
компонент может вызывать серверный обработчик события при клике мышкой. EventReceiver
– может
иметь методы - обработчики события SubmitDataRequest
– компонент принимает данные с формы.Большинство пользовательских методов страницы (в которых реализуется бизнес-логика страницы) как правило являются обработчиками событий. Например: клик по ссылке, отправка формы, навигация по странице и т.д.
Для назначения обработчика компоненту-инициатору указывается объект-получатель
(обычно $this
- объект класса страницы) и имя метода-обработчика в текстовом виде.
Метод-обработчик содержит параметр $sender
– ссылку на объект-источник (одно и тоже
событие может быть назначено нескольким компонентам) и, при необходимости, дополнительные
параметры.
В адресной строке фреймворк формирует номер страницы и иерархию компонентов, в
которой находится источник. При обработке запроса бекенд компоненты, являющиеся контейнерами,
будут передавать вызов компоненту, ID
которого следующее в иерархии, вплоть до
последнего – инициатора события (то есть по фронтенду которого например кликнули мышкой).
Механизм событий избавляет разработчика от забот по функционированию страницы, разборе запроса и формированию ответа клиенту. Разработчик работает с методами событий аналогично приложениям типа Delphi или WinForms.
Позволяет связать переменную или свойство класса с данными компонента для того, чтобы работать не с компонентами напрямую, а с переменными или полями бизнес-объектов.
Например, при биндинге компонента Label
с полем страницы $msg
в функциях
бизнес-логики достаточно присвоить значение полю и текст будет выведен на
страницу компонентом Label
. Если, например, какая-либо переменная привязана
к компоненту TextInput
при вводе данных с поля формы, значение поля автоматически
присвоится переменной. Биндинг задается ссылкой и именем привязываемого свойства.
<php
use \Zippy\PropertyBinding as Bind;
class Example2 extends \Zippy\Html\WebPage {
public $msg, $text;
public function __construct($params = null) {
$this->add(new Label('outputtext', new Bind($this, 'msg')));
$form = $this->add(new Form('form1'));
$form->onSubmit($this, 'OnSubmit');
$form->add(new TextInput('inputtext', new Bind($this, 'text')));
}
public function OnSubmit($sender) {
$this->msg = $this->text;
}
}
Основное назначение компонента DataView
-
вывод табличных данных.
Пример на основе демо приложения
<table >
<tr><th>ФИО</th><th>Возраст</th><th>> </th></tr>
<tr zippy="list"><td><span zippy="fio"></span></td>
<td><span zippy="age"></span></td>
<td><a zippy="edit">Редактировать></a> </td>
</tr>
</table>
public function __construct()
{
$this->add(new DataView('list',new DataSource(),$this,'listOnRow'))->Reload();
}
public function listOnRow($row){
//получаем объект данных, связанный со строкой
$item = $row->getDataItem();
//создаем компоненты в строке
$row->add(new Label('fio',$item->fio));
$row->add(new Label('age',$item->age));
$row->add(new ClickLink('edit'))->onClick($this,'editOnClick');
}
//обработчик редактирования
public function editOnClick($sender){
//получаем объект данных, связанный со строкой
$item = $sender->getOwner()->getDataItem();
//заполняем форму редактирования и т.д.
}
Для инициализации вывода необходим источник данных, возвращающий массив обьектов классов, реализующих интерфейс
DataItem
или
расширяющий класс
Entity
и
обработчик, в котором будут создаваться компоненты вывода.
Paginator
или
Pager
.
<div zippy="pag></div>
$this->add(new DataView('list',new DataSource(),$this,'listOnRow'));
//добавляем пагинатор для вывода
$this->add(new Paginator("pag",$this->list));
//устанавливаем количество строк на странице
$this->list->setPageSize(25));
$this->list->Reload();
DataView может использовать для вывода и другие блочные элементы, например, если надо вывести список товаров или галерею
рисунков.
Для примера выше (бекенд тот же)
<div class="row">
<div class="col-md-4" zippy="list">
<span zippy="fio"></span>
<span zippy="age"></span>
</div>
</div>
Компонент DataTable
предназначен для работы с тегом <table>. Компонент сам создает заголовки и пагинацию (если указано), но выводит
данные только в виде строк.
Компонент чаще всего используется для вывода различного рода репортов и прочих данных, не требующих бэкенд
компонентов.
При создании компонента нужно создать экземпляры столбцов с указанием необходимых параметров.
Для кастомизации вывода предусмотрено н обработчик setCellDrawEvent
рендеринга ячейки, которому
передается имя столбца и идентификатор записи.
Также можно установить обработчик setCellClickEvent
клика по ячейке
<table zippy="report></div>
//выводим таблицу с заголовком и пагинатором
$this->add(new \Zippy\Html\DataList\DataTable("report", new DataSource(), true, true));
// создаем столбцы с указанием сортировки
$this->report->addColumn(new Column('fio', 'ФИО', true ));
$this->report->addColumn(new Column('age', 'Возраст', true ));
Источник данных - промежуточный компонент, унифицирующий передачу данных от разных источников
компонентам
DataView
и DataTable
.
Источник данных должен реализовать интерфейс DataSource
. Методы интервейса предписывают
реализацию источником
условий выборки, сортировки и пагинации.
Существует несколько видов источников.
ArrayDataSource
ArrayDataSource применяется в случае использования массивов как набора данных. Если массив
может изменятся в процессе работы, следует передавать массив не напрямую, а использовать биндинг (см. демо
приложение).
EntityDataSource
EntityDataSource применяется для работы с Entity
. Источнику передается как параметр имя класса
сущности, унаследованной от Entity.
Пользовательский источник
Для сложных выборок разработчик может создать свой класс источника данных
и, если нужно, связать его с компонентами страницы (например, фильтрацией).
class DocDataSource implements \Zippy\Interfaces\DataSource
{
private function getWhere()
{
//возвращает условие для SQL запроса
return $where;
}
public function getItemCount()
{
//количество для пагинатора
return Document::findCnt($this->getWhere());
}
public function getItems($start, $count, $sortfield = null, $asc = null)
{
//выбирает данные
$docs = Document::find($this->getWhere(), "document_date desc,document_id desc", $count, $start);
return $docs;
}
public function getItem($id)
{
}
}
используется как обычный источник
$this->add(new DataView('list',new DocDataSource(),$this,'listOnRow'))->Reload();
Наследование страниц предназначено для решения проблемы "единообразия" страниц. Если необходимо иметь на сайте меню, логотип и прочие неизменяемые от страницы к странице части, тогда нужно разместить их в базовой странице, а изменяемый контент вынести в дочерние. На уровне классов дочерняя страница просто наследуется от базовой, наследуя все ее компоненты и обработчики, на уровне разметки - содержимое тэга BODY дочерней страницы вкладывается внутрь базовой вместо тэга <childpage/>.
Если в шаблоне дочерней страницы в <head> есть метатеги <title>,<description> и <keyword>, при рендеринге дочерней страницы эти теги будут перенесены с заменой в базовый шаблон.
Дочерние страницы имеют доступ ко всем компонентам, объявленным в родительской и
может ими управлять. Например подсвечивать текущий пункт меню.
Как пример - страница Base в демо приложении, от которой наследуются остальные.
Фрагмент страницы - это самостоятельный блок, который добавляется в страницу как обычный компонент,
но при этом имеет свой шаблон (загружается аналогично шаблону страницы). Используется, если на
некоторых страницах необходимо иметь один и тот же блок данных. Например: форма поиска, блок
вывода рекламы и т.д. Фрагмент может содержать любые другие компоненты и обработчики событий
как обычная страница. В разметку страницы компонент обычно добавляется с помощью тэга DIV.
Создается класс фрагмента наследованием от класса PageFragment
, который, в свою очередь,
наследован
от HtmlContainer
.
Пользовательский компонент позволяет програмно сформировать произвольное содержимое для тэга
(как правило DIV). Для создания пользовательского компонента (по сути пользовательского тэга) нужно
создать класс-наследник от CustomComponent
и перегрузить абстрактный
метод getContent()
.
Этот метод должен вернуть HTML код, который будет записан в тэг в шаблоне страницы, предназначенный
для вывода компонента.
Поскольку фреймворк автоматически обеспечивает сохранность состояния страницы, использование
AJAX
в Zippy
менее востребовано по сравнению с другими решениями. Тем не менее ряд компонентов могут использовать асинхронную
обработку событий.
Как правило использование AJAX
не требует какого-то особого кодирования и настройки.
Например, для AJAX
обработчика onClick()
по клику на ссылке для компонента
ClickLink
нужно только
указать третий параметр как true. Для отправки формы через AJAX
используется компонент AjaxSubmitLink
. Обработчики события и бизнес-логика страницы выполняются
аналогично обычному синхронному.
Также многие компоненты имеют возможность обновляться на странице после AJAX
вызова.
Поскольку обычный рендеринг всей страницы в этом случае не выполняется,
необходимо указать обновляемые элементы в обработчике события (метод страницы updateAjax()
).
Для этих компонентов (реализующих интерфейс AjaxRender
)
формируется клиентский скрипт, который обновляет их после AJAX
ответа.
$this->add(new ClickLink('time'))->onClick($this,'OnClick',true);
$this->add(new Label('msg'));
// ...
public function OnClick($sender) {
$this->msg->setText('Я обновлен через AJAX');
//указываем обновляемые компоненты
$this->updateAjax('msg');
}
В некоторых случаях необходимо вызвать метод страницы,
не связанный с каким-либо компонентом. Вызов выполняется асинхронно с помощью AJAX запроса.
В общем случае вызываемый метод выглядит так:
public function MyMethod($p, $post) {
return "Привет";
}
Где $p - массив параметров, если они были переданы в строке запроса,
$post - данные (raw) отправленые в случае POST запроса.
callPageMethod('MyMethod',[],null,function(answerdata){
})
где Переключение сменяемых дизайнов осуществляется путем простого переключения пути к
файлам в методе getTemplate()
приложения. Например, файлы шаблонов страницы можно
расположить в разных папках.
Роутинг осуществляется перегрузкой метода Route() приложения (см. выше пример для WebApplication) .
Функция принимает параметром URI и загружает страницу, соответствующую вызову.
Если присутствуют параметры, они идут через прямой слеш и передаются конструктору страницы.
Например, для /user/2
конструктор страницы будет public function __construct($id)
.
Поскольку содержимое страниц уже сериализуется и хранится в объекте сессии, а объект сессии в нагруженых приложениях обычно закеширован, то кеширование страниц не требует специального решения.
Применение вспомагательного шаблонизатора (используется Mustache)
не совсем согласуется с компонентной архитектурой фреймворка. Но, как показала практика, иногда использование
компонентов только для вывода
текстов и управления видимостью элементов страницы получается несколько громоздким, поскольку данные операции
фактически не требуют
бэкенд обьектов. В этих случаях можно использовать более традиционый шаблонизатор.
Данные для шаблонизатора присваиваются массиву _tvars
, члену класса WebPage
.
Страница может не содержать компонентов, а только независимые методы, вызываемые с помощью javascript функции
callPageMethod
(см. выше).
Это позволяет делать страницы в SPA стиле, которые не перезагружаются (до смены страницы) при запросе к серверу.
Серверный код страницы в таком случае работает как Web Api. При этом сохраняется работа PHP сессий,
в частности, не требуется отдельная авторизация. Как пример, страница АРМ кухни в складской системе сделаная на Vue.
<label data-label="paynotes" for="paynotes" > Комментарий к оплате</label>
<input class="form-control" type="text" zippy="paynotes">
Если поле ввода paynotes будет скрыто функцией setVisible(false)
,
лейбл скроется вместе с ним.
<a zippy="deleteitem">Удалить итем </a>
,
<script>
function check_deleteitem() {
return confirm("Удалить итем?")
}
</script>
Если функция вернет false, серверный обработчик вызван не будет.
Библиотека представляет собой набор компонентов, построенных на расширении
стандартных компонентов фреймворка. Библиотека не входит в ядро фреймворка и
располагается в отдельном пространстве имен ZCL
.
Библиотека состоит из следующих компонентов:
Компонент представляет собой реализацию серверной части для jquery.ganttview.
Компонент реализует функциональность простейшей капчи полностью инкапсулируя генерацию кода, рисунка, формирование ссылки на рисунок и, если задан соответствующий параметр, асинхронное обновление капчи по клику на рисунке.
Для реализации собственного алгоритма достаточно отнаследоваться от компонента и переопределить метод
OnCode
для генерации кода и/или метод OnImage
для генерации изображения.
Описание методов на странице API.
<img>
.
Нeсколько компонентов для работы с базами данных. Компоненты базируются на библиотеке ADODB,
что позволяет писать код, защищенный от sql-инъекций и переносимый между разными типами БД.
(На данный момент основные компоненты работы с БД выделены в отдельный
проект ZDB)
TreeEntity
- класс-наследник Entity
, предназначенный для работы с
иерархически
организованными сущностями. В дополнение к функционалу родительского класса имеет возможномть манипулировать
дочерними элементами
(поиск по дереву, удаление, перемещение веток), строить дерево для компонента Tree
на основе набора
данных из БД. Данные должны быть организованы
в соответствии с алгоритмом материализованного пути.
EntityDataSource
-
универсальный источник данных, реализующий интерфейс DataSource
,
позволяющий связать страничные компоненты табличного и списочного вывода с БД. В параметрах класса задаются имя
класса-сущности (Entity) и, при необходимости,
условие для выборки. Это позволяет разработчику избежать создания специализированного источника для простых линейных
выборок.
Некоторые компоненты, базирующиеся на Twitter Bootstrap.