Zend 2 FieldSets 的最佳实践,针对每种特定情况重新使用或重新创建它们?
Best practice for Zend 2 FieldSets, re-use them or re-create them for every specific situation?
我和我的同事争论我们是否应该在我们的项目中重新使用某些 Zend2 FieldSet classes。
使用该框架,我们创建了许多不同的表单,并且有相当多的表单需要填写相同的信息。
例如,我们有一个创建新员工的表单和一个创建新联系人的表单。两个表单都需要填写联系信息,所以两个表单都在表单中添加一个AccountFieldSet。
目前,对于每个新表单,都会创建一个新的 AccountFieldSet,因此我们有 Customer\Form\Contact\AccountFieldset 和 Employee\Form\AccountFieldSet,它们都包含如下代码:
<?php
namespace Employee\Form;
use Zend\InputFilter\InputFilterProviderInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Zend\Form\Fieldset;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use OurProject\Entity\Account;
class AccountFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $oObjectManager)
{
parent::__construct('account');
$this->setHydrator(new DoctrineObject($oObjectManager))->setObject(new Account());
$oAccountAddressFieldset = new AccountAddressFieldset($oObjectManager);
$this->add($oAccountAddressFieldset);
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'listGender',
'options' => array(
'empty_option' => '',
'object_manager' => $oObjectManager,
'target_class' => 'OurProject\Entity\ListGender',
'property' => 'name'
),
'attributes' => array(
'class' => 'select2',
'data-placeholder' => 'Gender'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'firstname',
'attributes' => array(
'class' => 'form-control input-xs',
'placeholder' => 'First name',
'required' => 'required'
)
));
我的同事认为这是正确的方法,因为也有一些表单并不是 Contact 的每个字段都应该出现,然后重新使用该 FieldSet 会通过加载更多必要的信息来提供额外的开销.
我反过来认为让两个 class 具有(几乎)相同的代码总是不好的做法,因此我们应该重新使用相同的 class,并且只创建一个新的一个实际上存在差异的情况。这样我们就不会在不同的地方有相同的代码,这应该减少我们应该更改代码的地方的数量,如果发生变化的话。
或者,我建议应该有一个基础 class,其中包含称为 BaseContactFieldSet 的最小 FieldSet,它包含所有表单将始终使用的所有字段,并且其他 FieldSet classes 应该扩展 class 并添加任何不在 BaseContactFieldSet 中的输入元素。
我的同事认为每个表单都有太多的异常,因此有必要在不同的地方创建很多重复的代码,我们不应该重复使用 FieldSet classes完全防止创建代码来处理异常。
所以我们想知道其他人的想法。我们应该尽可能多地重复使用代码,还是应该创建重复代码,因为特定表单可能会有例外?
最佳做法是 DRY 方法(不要重复自己)而不是 WET 方法(将所有内容都写两次)。
将通用元素添加到 AccountFieldset(此处考虑抽象 class),然后使用 EmployeeAccountFieldset 和 CustomerAccountFieldset 对其进行扩展。
使用 FormElementManager 服务注册具体的字段集 classes 然后您可以从任何您有权访问 serviceManager 的地方访问字段集对象,它们将被延迟加载,所以如果您不调用服务,他们永远不会被实例化。
在您的模块配置中:
return [
'form_elements' => [
'invokables'=>[
'MyNameSpace\Form\Fieldset\EmployeeAccount'=>'MyNameSpace\Form\Fieldset\EmployeeAccountFieldset'
]]];
如果您需要 add/remove 特定元素以用于特定用途,您还可以调整 fieldsetObjects(而不是 class 本身)。
//get fieldset object via the FormElementManager ServiceManager
$employeeAccountFieldset=$this->getServiceLocator()->get('FormElementManager')->get('MyNameSpace\Form\Fieldset\EmployeeAccount');
//remove password element
$employeeAccountFieldset->remove('password');
//tweak an element
$employeeAccountFieldset->get('email')->setAttribute('class','myCSSClass');
//add tweaked fieldset to form
$myFormObject->add($employeeAccountFieldset);
我和我的同事争论我们是否应该在我们的项目中重新使用某些 Zend2 FieldSet classes。 使用该框架,我们创建了许多不同的表单,并且有相当多的表单需要填写相同的信息。 例如,我们有一个创建新员工的表单和一个创建新联系人的表单。两个表单都需要填写联系信息,所以两个表单都在表单中添加一个AccountFieldSet。
目前,对于每个新表单,都会创建一个新的 AccountFieldSet,因此我们有 Customer\Form\Contact\AccountFieldset 和 Employee\Form\AccountFieldSet,它们都包含如下代码:
<?php
namespace Employee\Form;
use Zend\InputFilter\InputFilterProviderInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Zend\Form\Fieldset;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use OurProject\Entity\Account;
class AccountFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $oObjectManager)
{
parent::__construct('account');
$this->setHydrator(new DoctrineObject($oObjectManager))->setObject(new Account());
$oAccountAddressFieldset = new AccountAddressFieldset($oObjectManager);
$this->add($oAccountAddressFieldset);
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'listGender',
'options' => array(
'empty_option' => '',
'object_manager' => $oObjectManager,
'target_class' => 'OurProject\Entity\ListGender',
'property' => 'name'
),
'attributes' => array(
'class' => 'select2',
'data-placeholder' => 'Gender'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'firstname',
'attributes' => array(
'class' => 'form-control input-xs',
'placeholder' => 'First name',
'required' => 'required'
)
));
我的同事认为这是正确的方法,因为也有一些表单并不是 Contact 的每个字段都应该出现,然后重新使用该 FieldSet 会通过加载更多必要的信息来提供额外的开销.
我反过来认为让两个 class 具有(几乎)相同的代码总是不好的做法,因此我们应该重新使用相同的 class,并且只创建一个新的一个实际上存在差异的情况。这样我们就不会在不同的地方有相同的代码,这应该减少我们应该更改代码的地方的数量,如果发生变化的话。
或者,我建议应该有一个基础 class,其中包含称为 BaseContactFieldSet 的最小 FieldSet,它包含所有表单将始终使用的所有字段,并且其他 FieldSet classes 应该扩展 class 并添加任何不在 BaseContactFieldSet 中的输入元素。
我的同事认为每个表单都有太多的异常,因此有必要在不同的地方创建很多重复的代码,我们不应该重复使用 FieldSet classes完全防止创建代码来处理异常。
所以我们想知道其他人的想法。我们应该尽可能多地重复使用代码,还是应该创建重复代码,因为特定表单可能会有例外?
最佳做法是 DRY 方法(不要重复自己)而不是 WET 方法(将所有内容都写两次)。
将通用元素添加到 AccountFieldset(此处考虑抽象 class),然后使用 EmployeeAccountFieldset 和 CustomerAccountFieldset 对其进行扩展。
使用 FormElementManager 服务注册具体的字段集 classes 然后您可以从任何您有权访问 serviceManager 的地方访问字段集对象,它们将被延迟加载,所以如果您不调用服务,他们永远不会被实例化。
在您的模块配置中:
return [
'form_elements' => [
'invokables'=>[
'MyNameSpace\Form\Fieldset\EmployeeAccount'=>'MyNameSpace\Form\Fieldset\EmployeeAccountFieldset'
]]];
如果您需要 add/remove 特定元素以用于特定用途,您还可以调整 fieldsetObjects(而不是 class 本身)。
//get fieldset object via the FormElementManager ServiceManager
$employeeAccountFieldset=$this->getServiceLocator()->get('FormElementManager')->get('MyNameSpace\Form\Fieldset\EmployeeAccount');
//remove password element
$employeeAccountFieldset->remove('password');
//tweak an element
$employeeAccountFieldset->get('email')->setAttribute('class','myCSSClass');
//add tweaked fieldset to form
$myFormObject->add($employeeAccountFieldset);