Использовать декоратор или по старинке?

SiZE

Новичок
Вопрос связан с предыдущей моей темой. Заполняется массив мета данных формы:

PHP:
$form = array(
    /*
    array(
        'xtype' => 'textfield',
        'name' => 'lastname',
        'fieldlabel' => 'Фамилия'
    )
    */
    Field::init('lastname')->getTemplate(),
    /*
    array(
        'xtype' => 'textfield',
        'name' => 'firstname',
        'fieldlabel' => 'Имя'
    )
    */
    Field::init('firstname')->getTemplate(),
    /*
    array(
        'xtype' => 'textfield',
        'name' => 'surname',
        'fieldlabel' => 'Отчество'
    )
    */
    Field::init('surname')->getTemplate(),
);

Метод getTemplate возвращает массив, который является шаблоном для сущности которую описывает класс:

PHP:
public $template = array(
    'xtype' => 'textfield',
    'name' => 'lastname',
    'fieldlabel' => 'Фамилия'
);

Иногда необходимо бывает обернуть шаблон:

PHP:
public $template = array(
   'xtype' => 'fieldset',
   'autoHeight' => true,
   'items' => array(
      array(
         'xtype' => 'textfield',
         'name' => 'lastname',
         'fieldlabel' => 'Фамилия'
      )
   )
);
Как это лучше реализовать? Самое простое конечно, но не удобно использовать и наследовать:

PHP:
array(
    array(
        'xtype' => 'fieldset',
        'autoHeight' => true,
        'items' => array(
            Field::init('lastname')->getTemplate(),
        )
    ),
    Field::init('firstname')->getTemplate(),
    Field::init('surname')->getTemplate(),
);
Может сделать извращенный паттерн декоратор?

PHP:
$form = array(
    // Передача 
    Field::init('lastname')->applyDecorators('fieldset'=>array('autoHeight' => true))->getTemplate(),
    Field::init('firstname')->getTemplate(),
    Field::init('surname')->getTemplate(),);

class Field {
    public function applyDecorators($decorators){
        $field = $this;
        foreach ($decorators as $decorator => $params) {
            // В этом месте декоратор получает объект поля и делает с ним что хочет, возвращая измененный объект поля :)
            $field = new $decorator($field, $params);
        }
        return $field;
    }
}
 

WMix

герр M:)ller
Партнер клуба
я не понял в чем проблема, почему Field а не FieldSet implements Decorable{ function applyDecorators($decorators); } ?
 

SiZE

Новичок
я не понял в чем проблема, почему Field а не FieldSet implements Decorable{ function applyDecorators($decorators); } ?
У меня нет никаких идей на этот счет. Я не знаю с чего начать, хочу чтобы меня подтолкнули или подсказали решение. Задача такая, поля идут друг за другом (я тут просто голый HTML приведу, чтобы было понятней):

PHP:
<div><input /></div>
<div><input /></div>
<div><input /></div>
<!-- и тут одно поле или несколько полей надо обернуть в fieldset -->
<fieldset>
    <div><input /></div>
    <div><input /></div>
</fieldset>
<!-- или вообще в колоночный макет, я тут забустрапил, чтобы понятней было -->
<div class="row">
   <div class="col-sm-6">
      <div><input /></div>
      <div><input /></div>
   </div>
   <div class="col-sm-6">
      <div><input /></div>
      <div><input /></div>
   </div>
</div>
Я рассуждал так, если надо обернуть одно поле, то в классе Field используем метод applyDecorators. Если несколько полей, то надо создать класс, например, FieldGroup и так же у него вызывать applyDecorators.

Надеюсь понятно объяснил, как я мыслил. В итоге хочется добиться следующего: в базовой модели например мы используем какой-то декоратор, а если для региона его надо убрать, тогда наследуемся и легко избавляемся от него. Как добиться этой легкости? :)
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
В zend_form есть и филдсеты и сабформы и декораторы, так что во view достаточно form->render() написать. Но гибкий способ это когда view_script описываешь, а там рисуй как хочешь и можно фиелдсетами не заморачиваться. И вскоре я так и писал. У формы самое важное - валидация и фильтрация данных
 

AmdY

Пью пиво
Команда форума
Для zend form вроде был специальный рендер, который формы умел готовить под extjs4
 

SiZE

Новичок
Я посмотрю конечно архитектуру нового зенда. А по теории есть что? :)
 

AmdY

Пью пиво
Команда форума
По теории - делай как проще, потому что у тебя оба варианта полумеры. Либо ты работаешь с массивами, либо делаешь объекты, в том числе FieldSet, как писал @WMix.
PHP:
(new FieldSet())->autoHeight(true)->addField(new Field('lastname')),
А с декоратором у тебя получается этакая попытка вписать квадратное в жёлтое.
 
  • Like
Реакции: SiZE

Тугай

Новичок
По теории, если надо избавляться от if else, то пользуются фабричным методом, а не декоратором. :)
 

SiZE

Новичок
PHP:
(new FieldSet())->autoHeight(true)->addField(new Field('lastname')),
А с декоратором у тебя получается этакая попытка вписать квадратное в жёлтое.
Хорошо. А как поступить если мне надо обернуть поле/поля в массив со случайным набором параметров? Создать какой-то общий для этого случая класс или каждый раз новый? Приведу для примера, тут нет какого-то xtype или указания на конкретный элемент, это просто, так скажем декоратор в ExtJS, которому указывается набор дочерних элементов или других декораторов:

PHP:
array(
    'layout' => 'column',
    'defaults' => array(
        'width' => '25%',
        'columnWidth' => 0.25
    ),
    'items' => array( /* тут массив полей */ )
)
 

Тугай

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

Так нам не придется писать код типа if ($region == 1 && $tab == 'adress' ) { ... } elseif ($region == 5) { ... }.
И для изменений конкретного региона не придется вычитывать все эти if, а нужно будет просто открыть класс нужного региона (это и есть фабричный метод).

$template = FormFactory::getTemplateClass($region)->getTemplate();
 

SiZE

Новичок
$template = FormFactory::getTemplateClass($region)->getTemplate();
У нас модели по регионам автоматом подтягиваются, это то я конечно сделаю, но для каждого региона нет смысла копировать форму, иначе будет сложно поддерживать. Нужна возможность добавить/убавить минимальными движениями.
 
Сверху