
Доброго часу доби, хабражітель!
Трохи більше року тому зіткнувся з ситуацією коли потрібно було реалізувати веб-додаток (як звичайно в дуже стислі терміни) з багатим функціоналом:
- Служба захисту користувачів з різними ролями
- Призначення завдань на користувачів і відстеження подальшої життєдіяльності цих завдань
- Планування роботи користувачів (на день, місяць)
- Робота з результатами роботи співробітників (реєстрація часу і типів робіт)
- Формування різних звітів, статистичних зрізів інформації і тп
Я навмисне пропущу аналіз і вибір засобів реалізації та відразу перейду до найцікавішого: в якості платформи був обраний Koala Framework — гримуча суміш з Zend Framework і ExtJS. В основу цього фреймворку лягла модель MVC (model-view-controller). Але справжньою його силою є автогенеріруемие форми і таблиці (AutoForm і AutoGrid ).
Сенс авто-форм і авто-таблиць в тому, що розробнику потрібно описати модель (таблицю БД) і зв'язати поля / свойст моделі з колонками таблиці і полями форми. Наприклад:
припустимо у нас є таблиця в MySQL:
CREATE TABLE IF NOT EXISTS `tasks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`userId` int NOT NULL,
`title` varchar(300) COLLATE utf8_unicode_ci,
`description` varchar(1000) COLLATE utf8_unicode_ci,
`startDate` date,
`endDate` date,
`status` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `userId` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Модель буде мати вигляд:
<?php
class Tasks extends Kwf_Model_Db
{
protected $_table = 'tasks';
}
Щоб відобразити список завдань необхідно створити контролер (точніше AutoGrid Controller):
<?php
class TasksController extends Kwf_Controller_Action_Auto_Grid
{
protected $_modelName = 'Tasks';
protected $_defaultOrder = array('field' => 'id', 'direction' => 'DESC');
protected $_paging = 30;
protected $_buttons = array('add');
public function indexAction()
{
$this->view->ext('Tasks');
}
protected function _initColumns()
{
$this->_columns->add(new Kwf_Grid_Column('title', trl('Title'), 200));
$this->_columns->add(new Kwf_Grid_Column_Date('endDate', trl('End Date'), 100))->setRenderer('checkDate');
}
}
Тут властивості класу описують поведінку: кількість елементів на сторінці (так, посторінковий висновок підтримується з коробки!), Модель даних, сортування вибірки (опіціонально) і можливі дії. З дій тут зазначено тільки додавання завдань, але доступні ще й видалення, збереження та експорт в Excel / PDF.
Тепер потрібно завантажити завдання тільки для конкретного залогіненним користувача. Для цього під фреймворці є глобальні змінні. Тепер легко задаємо умови для вибірки завдань у контролері:
protected function _getWhere()
{
$users = Kwf_Registry::get('userModel');
$ret = parent::_getWhere();
$ret['status = ?'] = 0;
$ret['userId = ?'] = $users->getAuthedUserId();
return $ret;
}
Відмінно, тепер користувач бачить тільки свої активні завдання!
Так, залишилося додати створення і зміна завдань. Для цього потрібен вже інший контролер (AutoForm Controller):
<?php
class TaskController extends Kwf_Controller_Action_Auto_Form
{
protected $_modelName = 'Tasks';
protected $_permissions = array('save', 'add');
protected $_buttons = array('save');
protected function _initFields()
{
$this->_form->add(new Kwf_Form_Field_TextField('title', trl('Title')))
->setWidth(400)
->setAllowBlank(false);
$this->_form->add(new Kwf_Form_Field_DateField('startDate', trl('Start Date')));
$this->_form->add(new Kwf_Form_Field_DateField('endDate', trl('End Date')));
$this->_form->add(new Kwf_Form_Field_TextArea('description', trl('Description')))
->setHeight(70)
->setWidth(400);
$this->_form->add(new Kwf_Form_Field_Checkbox('status', trl('Done')));
}
}
Властивості класу описують поведінку форми, причому зв'язку даних з полями задаються у функції initFields (). Але є маленька проблема: поле userId ніяк не пов'язано з поточним користувачем і не прив'язане до полів форми. Поки що… Щоб звільнити користувача від роботи з вибору самого себе в якості власника завдання потрібно додати тригер — функцію, що спрацьовує під час створення нового запису:
protected function _beforeInsert(Kwf_Model_Row_Interface $row)
{
$users = Kwf_Registry::get('userModel');
if ($row->startDate == NULL)
{
$row->startDate = new DateTime ();
}
$row->userId = $users->getAuthedUserId();
$row->status = 0;
}
У KWF також доступні й інші тригери: на зміну і видалення даних.
Тепер якось треба зв'язати обидва цих контролера між собою. Код обох контролерів генерує ExtJS форми. Отже і пов'язувати ми їх будемо в JS коді:
var Tasks = Ext.extend(Ext.Panel,
{
initComponent : function(test)
{
var form = new Kwf.Auto.FormPanel({
controllerUrl : '/task',
region : 'center'
});
var grid = new Kwf.Auto.GridPanel({
controllerUrl : '/tasks',
region : 'west',
width : 400,
resizable : true,
split : true,
collapsible : true,
title : trl('Tasks'),
bindings: [{
queryParam: 'id',
item: form
}]
});
this.layout = 'border';
this.items = [grid, {
layout: 'border',
region: 'center',
items: [form]
}];
Tasks.superclass.initComponent.call(this);
}
});
Всім, хто вже працював з ExtJS, цей код напевно здасться дуже знайомим =)
Залишилося тільки визначити точку доступу (входу) до цих контролерам. Для цього в KWF є окремий зумовлений клас Kwf_Acl:
<?php
class Acl extends Kwf_Acl
{
public function __construct()
{
parent::__construct();
$this->remove('default_index');
$this->addResource(new Kwf_Acl_Resource_MenuUrl('default_tasks', array('text'=>trl('Tasks'), 'icon'=>'time.png'), '/tasks'));
$this->addResource(new Zend_Acl_Resource('default_task'), ‘default_tasks');
$this->addRole(new Zend_Acl_Role(‘user'));
$this->allow('user', 'default_tasks');
$this->allow('admin', 'default_tasks');
$this->allow('admin', 'default_index');
}
}
Ось і все! Черговий TO-DO список готовий! У добавок він розрахований на багато і при необхідності завдання типу експорт списку в Excel / PDF, фільтрації і сортування списків додаються максимум хвилин за 5!

Повний код програми доступний тут: github.com / kronik / kwf-app-demo
Давайте створювати побільше корисних і зручних інструментів! =)
Від себе ще хочу додати що зараз веб-додаток на KFW успішно розроблено та впроваджено в крупній Російської компанії. Відгуки користувачів виключно позитивні.
PS: У команду шукаються розробники PHP, ExtJS, MySQL, бажаючі ближче познайомитися з Koala Framework і готові допомогти (не безкоштовно звичайно) у розвитку вітчизняної спеціалізованої КІС. На всі питання можу відповісти в коментарях або в личке.
Джерело: Хабрахабр