如何创建扩展Doctrine实体选择元素的自定义表单元素

时间:2013-02-14 03:58:12

标签: zend-framework2

我正在尝试创建一个自定义元素,我可以预先设置一个实体名称空间 - Application\Entity\User并轻松地将该元素添加到任何表单中。我有一个问题,在表单元素中注入doctrine em - 我在配置中找到了关于form_elements键的帖子,但它不起作用 - 所以我想可能只是设置元素并从表单中传递objectmanager

我想做这样的事情。

$this->add(
    array(
        'name' => 'user_id',
        'type' => 'Application\Form\Element\UserSelect',
        'options' => array(
            'label'          => 'User',
            'object_manager' => $this->getObjectManager(),
        ),
    ),
);

或者甚至更好

$this->add(
    array(
        'name'  => 'user_id',
        'type'  => 'Application\Form\Element\UserSelect',
        'label' => 'User',
    ),
);

module.config.php

'service_manager' => array(
    'aliases' => array(
        'doctrine_service' => 'doctrine.entitymanager.orm_default',
    ),
    'initializers' => array(
        function ($instance, $sm) {
            if ($instance instanceof DoctrineModule\Persistence\ObjectManagerAwareInterface) {
                $instance->setObjectManager(
                    $sm->get('doctrine_service')
                );
            }
            if ($instance instanceof Application\Form\AbstractForm) {
                $instance->init();
            }
        },
    ),
),

AbstractForm.php

namespace Application\Form;

use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Zend\Form\Form as ZendForm;

abstract class AbstractForm extends ZendForm implements ObjectManagerAwareInterface
{
    protected $objectManager;
    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;
    }
    public function getObjectManager()
    {
        return $this->objectManager;
    }
}

TestForm.php

namespace Users\Form;

use Application\Form\AbstractForm;

class Login extends AbstractForm
{
    public function init()
    {
        $this->add(
            array(
                'name' => 'user_id',
                'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity',
                'options' => array(
                    'label'          => 'User',
                    'object_manager' => $this->getObjectManager(),
                    'target_class'   => 'Application\Entity\User',
                    'property'       => 'name',
                    'find_method' => array(
                        'name'   => 'findBy',
                        'params' => array(
                            'criteria' => array('is_deleted' => 0),
                            'orderBy'  => array('name' => 'ASC'),
                        ),
                    ),
                ),
            ),
        );
    }
}

1 个答案:

答案 0 :(得分:2)

初始值设定项 invokables 添加到Module.php的 getFormElementConfig 方法中:

use DoctrineModule\Persistence\ObjectManagerAwareInterface;
...
public function getFormElementConfig()
{
    return array(
    'invokables' => array(
    'MyForm' => 'Application\Form\MyForm',
        ),
        'initializers' => array(
            'ObjectManagerInitializer' => function ($element, $formElements) {
                if ($element instanceof ObjectManagerAwareInterface) {
                    $services      = $formElements->getServiceLocator();
                    $entityManager = $services->get('Doctrine\ORM\EntityManager');

                    $element->setObjectManager($entityManager);
                }
            },
        ),
    );
}

然后使用 FormElementManager 获取te form:

$forms = $this->getServiceLocator()->get('FormElementManager');
$myForm = $forms->get('MyForm');

最后在 init 方法中添加你的元素 - 而不是构造函数,因为他永远不会知道 objectManager

public function init()
{
    $this->add(
        array(
            'name' => 'user_id',
            'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity',
            'options' => array(
                'label'          => 'User',
                'object_manager' => $this->getObjectManager(),
                'target_class'   => 'Application\Entity\User',
                'property'       => 'name',
                'find_method' => array(
                    'name'   => 'findBy',
                    'params' => array(
                        'criteria' => array('is_deleted' => 0),
                        'orderBy'  => array('name' => 'ASC'),
                    ),
                ),
            ),
        ),
    );
}

See a discussion on this setup here.