Содержание

lmbFormCommand

Общее описание

lmbFormCommand используется для огранизации работы с формами.

lmbFormCommand в конструкторе принимает:

$validator = new NewslineValidator();
$template_path = 'news/create.html';
$form = new lmbFormCommand($template_path, 'newsline_form', $validator);

lmbFormCommand содержит методы, которые позволяют получить большой спектр информации о форме:

Форма считается отправленной, если в той части Запроса, которая касается формы (если возможно несколько форм на странице), есть свойство submitted и оно имеет положительное значение.

События lmbFormCommand

Класс lmbFormCommand реализован с применением паттернам Observer. Он может генерировать и принимать подписку на следующие события ( в скобках указаны методы для подписки на события):

Например, если форма была отправлена и все данные верны, то последовательно будут активизированы следующие подписчики: onBefore, onBeforeValidate, onValid, onAfterValidate, onAfter. Если формы была отображена в первый раз - то onBefore, onShow, onAfter.

Взаимодействие View c Controller в лице lmbFormCommand

Как данные из формы попадают в шаблон (View)? Мы полагаем, что вы кратко ознакомились со схемом организации View и представляете, для чего нужен lmbView и lmbRenderer.

Итак, первое - мы указываем название шаблона, который будет отрендерен после выполнения команды. Если вы используете шаблонную систему WACT (lmbWACTRenderer), значит внутри этого шаблона должен находиться компонент формы с идентификатором, совпадающим с названием формы, которое мы передали в конструктор lmbFormCommand.

Далее, во время выполнения lmbFormCommand команда самостоятельно передает во View свои данные и ошибки валидации, если они есть. А уже сам lmbWACTRenderer перенесет эти данные в компоненты шаблона.

Если вы не используете lmbWACTRenderer, то схема переноса этих данных может отличаться.

Пример использования lmbFormCommand

В качестве примера использования класса lmbFormCommand, приведем команду EditNewsCommand из CRUD приложения, которое идет в поставке с пакетом WEB_APP (ниже будут даны подробные комментарии):

lmb_require(LPKG_WEB_APP_DIR . '/src/command/lmbFormCommand.class.php');
lmb_require(LPKG_DBAL_DIR . '/src/lmbTableGateway.class.php');
 
class lmbEditNewsCommand extends lmbFormCommand
{
  protected $db_table;
  protected $newsline_id;
 
  function __construct()
  {
    parent :: __construct($template_path = 'news/edit.html',
                          $form_id = 'news_form',
                          $validator = new lmbHandle(LPKG_WEB_APP_DIR .  '/examples/crud/src/validator/lmbNewsValidator'));
 
    $this->db_table = new lmbTableGateway('news');
 
    $this->registerOnBeforeCallback($this, 'guard');
    $this->registerOnShowCallback($this, 'init');
    $this->registerOnValidCallback($this, 'updateOrPreview');
  }
 
  function guard($form)
  {
    if(!$this->newsline_id = $this->request->getInteger('id'))
    {
      $this->performCommand(LPKG_WEB_APP_DIR . '/src/command/lmbSet404ErrorViewCommand');
      $form->halt();
    }
  }
 
  function init($form)
  {
    if(($newsline_record = $this->db_table->selectRecordById($this->newsline_id)))
      $form->import($newsline_record->export());
    else
    {
      $this->performCommand(LPKG_WEB_APP_DIR . '/src/command/lmbSet404ErrorViewCommand');
      $form->halt();
    }
  }
 
  function updateOrPreview($form)
  {
    if($form->get('edit'))
    {
      $this->db_table->updateById($this->newsline_id, $form->export());
      $this->response->redirect('/');
    }
    elseif($form->get('preview'))
    {
      $this->setToView('show_preview', true);
    }
  }
}
?>

Теперь разберем все очень подробно:

class lmbEditNewsCommand extends lmbFormCommand
{
  [...]
 
  function __construct()
  {
    parent :: __construct($template_path = 'news/edit.html',
                          $form_id = 'news_form',
                          $validator = new lmbHandle(LPKG_WEB_APP_DIR . '/examples/crud/src/validator/lmbNewsValidator'));
 
    [...]
  }
 
} 

EditNewsCommand наследуется от lmbFormCommand и передает в родительский конструктор путь до шаблона, где определена форма, название формы news_form и валидатор NewsValidator (вернее хендл на валидатор).

  function __construct()
  {
    [...]
    $this->registerOnBeforeCallback($this, 'guard');
    [...]
  }
 
  function guard($form)
  {
    if(!$this->newsline_id = $this->request->getInteger('id'))
    {
      $this->performCommand(LPKG_WEB_APP_DIR . '/src/command/lmbSet404ErrorViewCommand');
      $form->halt();
    }
  }

Мы регистрируем слушателя на активацию формы (событие onBefore). Активация формы происходит каждый раз, когда вызывается метод lmbFormCommand :: perform(). Слушатель - это callback, который вызовает метод guard() самого класса EditNewsCommand. В методе guard мы проверяем наличие параметра id в Запросе. Если его нет, то вызывается команда lmbSet404ErrorViewCommand, которая поставит шаблон 404 ошибки, плюс при помощи метода halt() мы завершаем выполнение команды.

  function __construct()
  {
    [...]
    $this->registerOnShowCallback($this, 'init');
    [...]
  }
 
  function init($form)
  {
    if(($newsline_record = $this->db_table->selectRecordById($this->newsline_id)))
      $form->import($newsline_record->export());
    else
    {
      $this->performCommand(LPKG_WEB_APP_DIR . '/src/command/lmbSet404ErrorViewCommand');
      $form->halt();
    }
  }

Мы регистрируем слушателя на первоначальное отображение формы (событие onShow), который заключается в вызове метода init() самого класса команды EditNewsCommand. В методе init мы при помощи lmbTableGateway (db_table), загружаем данные о новости в контейнер данных формы. Если данных в базе данных нет, то вызывается команда lmbSet404ErrorViewCommand, которая поставит шаблон 404 ошибки, также мы завершаем выполнение команды.

  function __construct()
  {
    [...]
    $this->registerOnValidCallback($this, 'updateOrPreview');
    [...]
  }
 
  function updateOrPreview($form)
  {
    if($form->get('edit'))
    {
      $this->db_table->updateById($this->newsline_id, $form->export());
      $this->response->redirect('/');
    }
    elseif($form->get('preview'))
    {
      $this->setToView('show_preview', true);
    }
  }

Мы регистрируем слушателя на событие onValid, которое генерируется формой, когда она была отослана пользователем и все данные, которые необходимо было проверить при помощи валидатора, успешно прошли валидацию.

Метод updateOrPreview() проверяет, пришло ли поле «edit» с формы. Если пришло, это значит, что пользователь нажал на кнопку «edit» и запись в базе данных нужно обновить. После этого пользователь перебрасывается на главную страницу. Если же пришло поле «preview», значит пользователь нажал на кнопку «Preview» и необходимо показать зону шаблона preview. Для этого во View устанавливается переменная «show_preview». Сам шаблон самостоятельно решит, что делать с этой переменной. (см. базовый туториал)

Некоторым разработчикам использование слушателей может показаться слишком сложным. Однако это гарантирует легкое повторное использование кода, гибкость и широкие по возможности расширению команд.