В первой части этой серии мы говорили о проблемах развития, с которыми мы сталкиваемся, и о том, как Openbiz Cubi может помочь, предоставив надежную, готовую к использованию среду веб-приложений. В этой части мы увидим, как создать наш собственный модуль и немного углубиться в основную архитектуру фреймворка.
Сборка первого модуля
Давайте перейдем к захватывающей части — созданию модуля; мы начнем с простой страницы редактирования клиента. На этой странице пользователи могут создавать, обновлять и удалять клиентов.
 Сначала давайте сделаем таблицу базы данных customer .  SQL для создания таблицы: 
 CREATE TABLE customer (  id INTEGER NOT NULL AUTO_INCREMENT,  name VARCHAR(64) NOT NULL,  description VARCHAR(255) DEFAULT NULL,  address VARCHAR(255) DEFAULT NULL,  phone VARCHAR(20) DEFAULT NULL,  fax VARCHAR(20) DEFAULT NULL,  status INTEGER DEFAULT NULL,  create_by INTEGER DEFAULT '1',  create_time DATETIME DEFAULT NULL,  update_by INTEGER DEFAULT '1',  update_time DATETIME DEFAULT NULL,  PRIMARY KEY (id) ) ENGINE=InnoDB 
  Следующим шагом в создании модуля является создание файлов метаданных XML для страницы редактирования клиента.  Здесь мы используем gen_meta , команду генерации метаданных в gen_meta cubi/bin/tools . 
  / dev / cubi / bin / tools $ php gen_meta.php Клиент по умолчанию 
Вы можете просто нажать клавишу Enter, чтобы завершить работу мастера. После выполнения команды генерируются следующие файлы:
Файл конфигурации модуля
-  modules/customer/mod.xml
Модуль DO файл
-  modules/customer/do/CustomerDO.xml
Файл формы модуля
-  modules/customer/form/CustomerListForm.xml
-  modules/customer/form/CustomerDetailForm.xml
-  modules/customer/form/CustomerEditForm.xml
-  modules/customer/form/CustomerNewForm.xml
-  modules/customer/form/CustomerCopyForm.xml
Модуль Просмотр файла
-  modules/customer/view/CustomerListView.xml
Файлы виджетов модуля
-  modules/customer/widget/DashboardForm.xml
-  modules/customer/widget/LeftMenu.xml
Файлы шаблонов модулей
-  modules/customer/template/detail.tpl
-  modules/customer/template/detail_elementset.tpl
-  modules/customer/template/grid.tpl
-  modules/customer/template/view.tpl
  Затем мы загружаем только что созданный модуль командой load_module . 
/ dev / cubi / bin / tools / php $ load_module.php customer Начать загрузку клиентского модуля ... -------------------------------------------------- ------ [2013-01-26T17: 57: 16 + 08: 00] Загрузка модуля заказчика [2013-01-26T17: 57: 16 + 08: 00] Установить модуль заказчика [2013-01-26T17: 57: 16 + 08: 00] Установите ACL модуля. [2013-01-26T17: 57: 16 + 08: 00] Установить меню модуля. [2013-01-26T17: 57: 16 + 08: 00] Установить виджет модуля. [2013-01-26T17: 57: 16 + 08: 00] Установить ресурс модуля. [2013-01-26T17: 57: 16 + 08: 00] Установить журналы изменений модуля. [2013-01-26T17: 57: 16 + 08: 00] Скопируйте файлы ресурсов в папку / cubi / resources. [2013-01-26T17: 57: 16 + 08: 00] клиент загружен. Предоставить администратору доступ ко всем действиям модуля «клиент» -------------------------------------------------- ------ Клиентский модуль с конечной загрузкой
Давайте проверим модуль. Если вы уже вошли в Cubi, выйдите и войдите снова. Вы должны увидеть новую вкладку с именем «Клиент», появившуюся в разделе заголовка. Перейдите на вкладку, чтобы перейти на страницу «Панель управления клиентами», затем нажмите ссылку «Управление клиентами», чтобы перейти на страницу управления клиентами. Теперь мы можем создавать, обновлять, искать и удалять клиентов.
Под капотом
  Вы можете задаться вопросом без какого-либо программирования, как Openbiz Cubi заставляет все работать?  На предыдущих шагах gen_meta создавала XML-файлы в папке клиентского модуля.  Куби тогда знает, как интерпретировать эти файлы.  Давайте сначала mod.xml файл описания модуля mod.xml . 
Файл описания модуля
  Мы создали модуль customer с mod.xml modules/customer . 
 <?xml version="1.0" standalone="no"?> <Module Name="customer" Description="customer module" Version="0.1.0" OpenbizVersion="3.0"> <ACL> <Resource Name="customer"> <Action Name="Access" Description="Access Customer Module Dashboard"/> </Resource> <Resource Name="customer"> <Action Name="Access" Description="Access Customer"/> <Action Name="Manage" Description="Manage Customer"/> </Resource> </ACL> <Menu> <MenuItem Name="CustomerTop" Title="Customer" Description="Customer Description" URL="/customer/dashboard" Parent="" Order="10"> <MenuItem Name="Customer" Title="Customer" Description="Customer description" URL="" Order="10"> <MenuItem Name="Customer.List" Title="Customer Manage" Description="" URL="/customer/customer_list" Order="10"/> </MenuItem> </MenuItem> </Menu> <Dependency> <Module Name="system"/> </Dependency> </Module> 
  mod.xml содержит 3 раздела: 
-   Контроль доступа — раздел ACLопределяет ресурсы и их действия. Эти определения используются для управления разрешениями для определенных ролей.
-   Меню — раздел « Menu» определяет ссылки на страницы в навигационной системе (вкладки приложений, хлебные крошки и меню).
-   Зависимости — раздел Dependencyопределяет модули, от которых зависит текущий модуль. Зависимые модули должны быть установлены в первую очередь.
Обычно каждый модуль включает в себя свои собственные модели данных и XML-файлы презентации. Каркас имеет механизм метаданных, который может понимать XML и загружать данные и объекты пользовательского интерфейса на лету. Фреймворк в основном работает с двумя типами объектов метаданных:
- Объекты данных — Cubi отображает физические хранилища данных (например, таблицу базы данных) на логические объекты.
- Объекты формы и представления. Объекты формы описывают, как представлять данные объектов данных в блоке на странице, а объекты представления определяют контейнер объектов формы. В браузере представление совпадает с веб-страницей.
Объект данных
  Теперь давайте посмотрим на объект данных XML в modules/customer/do/CustomerDO.xml : 
 <?xml version="1.0" standalone="no"?> <BizDataObj Name="CustomerDO" Description="" Class="BizDataObj" DBName="Default" Table="customer" SearchRule="" SortRule="" OtherSQLRule="" Uniqueness="" Stateless="N" IdGeneration="Identity" CacheLifeTime="0" CreateCondition="customer.Manage" UpdateCondition="customer.Manage" DeleteCondition="customer.Manage"> <BizFieldList> <BizField Name="Id" Column="id" Type="Number"/> <BizField Name="name" Column="name" Length="64" Required="Y" Type="Text"/> <BizField Name="description" Column="description" Length="255" Required="N" Type="Text"/> <BizField Name="address" Column="address" Length="255" Required="N" Type="Text"/> <BizField Name="phone" Column="phone" Length="20" Required="N" Type="Text"/> <BizField Name="fax" Column="fax" Length="20" Required="N" Type="Text"/> <BizField Name="status" Column="status" Required="N" Type="Number"/> <BizField Name="create_by" Column="create_by" Type="Number" ValueOnCreate="{@profile:Id}"/> <BizField Name="create_time" Column="create_time" Type="Datetime" ValueOnCreate="{date('Ymd H:i:s')}"/> <BizField Name="update_by" Column="update_by" Type="Number" ValueOnCreate="{@profile:Id}" ValueOnUpdate="{@profile:Id}"/> <BizField Name="update_time" Column="update_time" Type="Datetime" ValueOnCreate="{date('Ymd H:i:s')}" ValueOnUpdate="{date('Ymd H:i:s')}"/> </BizFieldList> <TableJoins> </TableJoins> <ObjReferences> </ObjReferences> </BizDataObj> 
  XML определяет отображение между таблицей customer и объектом CustomerDO .  Он также определяет определенные правила для объектов, а также проверку, тип и значение каждого поля. 
Форма объекта
  Давайте также посмотрим на объект формы XML в modules/customer/form/CustomerListForm.xml . 
 <?xml version="1.0" encoding="UTF-8"?> <EasyForm Name="CustomerListForm" Class="EasyForm" FormType="List" jsClass="jbForm" Title="Customer Management" Description="" BizDataObj="customer.do.CustomerDO" PageSize="10" DefaultForm="Y" TemplateEngine="Smarty" TemplateFile="grid.tpl" Access="customer.Access"> <DataPanel> <Element Name="row_selections" Class="RowCheckbox" Label="" FieldName="Id"/> <Element Name="fld_Id" Class="ColumnText" FieldName="Id" Label="Id" Sortable="Y"/> <Element Name="fld_name" Class="ColumnText" FieldName="name" Label="Name" DefaultValue="New Customer" Sortable="Y" Link="javascript:"> <EventHandler Name="fld_name_onclick" Event="onclick" Function="SwitchForm(customer.form.CustomerDetailForm,{@:Elem[fld_Id].Value})" /> </Element> <Element Name="fld_description" Class="ColumnText" FieldName="description" Label="Description" Sortable="Y"/> <Element Name="fld_address" Class="ColumnText" FieldName="address" Label="Address" Sortable="Y"/> <Element Name="fld_phone" Class="ColumnText" FieldName="phone" Label="Phone" Sortable="Y"/> <Element Name="fld_fax" Class="ColumnText" FieldName="fax" Label="Fax" Sortable="Y"/> <Element Name="fld_status" Class="ColumnText" FieldName="status" Label="Status" Sortable="Y"/> </DataPanel> <ActionPanel> ... <Element Name="btn_delete" Class="Button" Text="Delete" CssClass="button_gray_m" Access="customer.Manage"> <EventHandler Name="del_onclick" Event="onclick" EventLogMsg="" Function="DeleteRecord()" ShortcutKey="Ctrl+Delete" ContextMenu="Delete"/> </Element> ... </ActionPanel> <NavPane> ... </NavPanel> <SearchPane> ... </SearchPanel> </EasyForm> 
  XML отображает поля из объектов данных в элементы пользовательского интерфейса.  Он также определяет панели для логического расположения элементов.  Для каждого элемента пользовательского интерфейса поведение взаимодействия может быть описано в его разделе EventHandler . 
Настроить объекты
  Каждый элемент Metadata поставляется с атрибутом Class .  В метаданных, сгенерированных gen_meta , для атрибута задан базовый класс платформы ( BizDataObj для объектов данных, EasyForm для объектов формы).  Разработчики могут просто заменить это для реализации специальной бизнес-логики.  Например, чтобы добавить специальную логику для удаления записи клиента, вы можете создать файл /modules/customer/form/CustomerForm.php и установить для него атрибут Class элемента Metadata .  Класс PHP может выглядеть так: 
 <?php class CustomerForm extends EasyForm { public function deleteRecord($id = null) { // add your logic here Parent::deleteRecord($id); // call parent deleteRecord method } } 
Кубический поток казни
Так что же происходит, когда в браузере вызывается http: //host/cubi/index.php/customer/customer_list ?
-   index.phpвызывает_forward.phpдля анализа URL. Он понимает, что / customer / customer_list указывает наcubi/modules/customer/view/CustomerListView.xmlв соответствии с соглашением об именах URL-адресов Кубы.
- Метод визуализации представления вызывается.
-   Метод render вызывает метод render включенной формы ( cubi/modules/customer/form/CustomerListForm.xml).
- Метод render формы вызывает методы запроса данных своего объекта данных.
- Методы запроса подготавливают SQL и выполняют его в отношении базы данных.
- Форма использует возвращенный набор данных из DO для генерации HTML со своим шаблоном.
- Представление использует выходные данные форм для генерации HTML со своим шаблоном.
- Сервер отправляет вывод HTML в браузер.
Как только представление загружается в браузер, большинство взаимодействий с пользователем происходит в формах через Ajax (без перезагрузки страницы). Диаграмма ниже показывает, как работает вызов Ajax:
Вывод
Из этой серии мы узнали, как установить Cubi, настроить систему и создать модуль. Вы также можете обнаружить, что файл метаданных XML легче изучать и поддерживать, чем программный код. Я надеюсь, что вам понравился этот сериал, и желаю вам удачи в ваших собственных бизнес-приложениях на Openbiz Cubi.
Изображение через Fotolia
