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);