Php 如何将Doctrine ObjectManager注入表单元素 我正在处理我的自定义用户模块,基本上使用ZfcUser作为基础。由于每个应用程序都是不同的,并且需要不同的关于用户的元信息,所以我希望可以使用配置数组轻松地对其进行配置

Php 如何将Doctrine ObjectManager注入表单元素 我正在处理我的自定义用户模块,基本上使用ZfcUser作为基础。由于每个应用程序都是不同的,并且需要不同的关于用户的元信息,所以我希望可以使用配置数组轻松地对其进行配置,php,zend-framework2,Php,Zend Framework2,在模块的全局配置文件中,我定义了自定义表单字段,在模块的onBootstrap中,我使用ZfcUser\form\Register的init事件扩展了ZfcUser注册表单。简而言之,我想这样做: $sharedEvents->attach('ZfcUser\Form\Register', 'init', function($e) use ($sm) {

在模块的全局配置文件中,我定义了自定义表单字段,在模块的onBootstrap中,我使用ZfcUser\form\Register的init事件扩展了ZfcUser注册表单。简而言之,我想这样做:

$sharedEvents->attach('ZfcUser\Form\Register',
                'init',
                function($e) use ($sm)
                {
                    /* @var $form \ZfcUser\Form\Register */
                    $form = $e->getTarget();

                    // Get relevant config
                    $config = $sm->get('config');
                    if ( array_key_exists('redev_user', $config) && is_array($config['redev_user']) )
                    {
                        if ( array_key_exists('custom_fields', $config['redev_user']) && is_array($config['redev_user']['custom_fields']) )
                        {
                            foreach ($config['redev_user']['custom_fields'] as $curCustomField)
                            {
                                $form->add($curCustomField);
                            }
                        }
                    }
[...]
<?php
return array(
    'redev_user' => array(
        'custom_fields' => array(
            // Custom fields which will be added to the registration form
            array(
                    'name' => 'firstname',
                    'type' => 'text',
                    'options' => array(
                            'label' => 'First name',
                    ),
            ),
array(
           'name' => 'country',
           'type' => 'DoctrineModule\Form\Element\ObjectSelect',
           'options' => array(
           'label' => 'Country',
           //'object_manager' => $sm->get('Doctrine\ORM\EntityManager'),
           'target_class'   => 'RedevUser\Entity\Country',
           'property'       => 'countryname',
           'is_method'      => false,
           'find_method'    => array(
               'name'   => 'findBy',
               'params' => array(
                               'criteria' => array(),
                                'orderBy'  => array('countryname' => 'ASC'),
                           ),
            ),
       ),
     ),
foreach ($config['redev_user']['custom_fields'] as $curCustomField)
{
    $formElemFactory = $form->getFormFactory();
    $elem = $formElemFactory->createElement($curCustomField);

    if ($elem instanceof \DoctrineModule\Form\Element\ObjectSelect)
    {
         // Inject ObjectManager
         $elem->getProxy()->setObjectmanager($sm->get('Doctrine\ORM\EntityManager'));
    }

    $form->add($elem);
}
然后,在我的配置文件中定义自定义表单字段,如下所示:

$sharedEvents->attach('ZfcUser\Form\Register',
                'init',
                function($e) use ($sm)
                {
                    /* @var $form \ZfcUser\Form\Register */
                    $form = $e->getTarget();

                    // Get relevant config
                    $config = $sm->get('config');
                    if ( array_key_exists('redev_user', $config) && is_array($config['redev_user']) )
                    {
                        if ( array_key_exists('custom_fields', $config['redev_user']) && is_array($config['redev_user']['custom_fields']) )
                        {
                            foreach ($config['redev_user']['custom_fields'] as $curCustomField)
                            {
                                $form->add($curCustomField);
                            }
                        }
                    }
[...]
<?php
return array(
    'redev_user' => array(
        'custom_fields' => array(
            // Custom fields which will be added to the registration form
            array(
                    'name' => 'firstname',
                    'type' => 'text',
                    'options' => array(
                            'label' => 'First name',
                    ),
            ),
array(
           'name' => 'country',
           'type' => 'DoctrineModule\Form\Element\ObjectSelect',
           'options' => array(
           'label' => 'Country',
           //'object_manager' => $sm->get('Doctrine\ORM\EntityManager'),
           'target_class'   => 'RedevUser\Entity\Country',
           'property'       => 'countryname',
           'is_method'      => false,
           'find_method'    => array(
               'name'   => 'findBy',
               'params' => array(
                               'criteria' => array(),
                                'orderBy'  => array('countryname' => 'ASC'),
                           ),
            ),
       ),
     ),
foreach ($config['redev_user']['custom_fields'] as $curCustomField)
{
    $formElemFactory = $form->getFormFactory();
    $elem = $formElemFactory->createElement($curCustomField);

    if ($elem instanceof \DoctrineModule\Form\Element\ObjectSelect)
    {
         // Inject ObjectManager
         $elem->getProxy()->setObjectmanager($sm->get('Doctrine\ORM\EntityManager'));
    }

    $form->add($elem);
}
请注意对象管理器的注释行。ObjectSelect元素显然需要ObjectManager。问题是如何在基于配置呈现表单时注入ObjectManager

我想自己呈现表单元素,然后检查它是否是doctriemodule\form\element的某个接口或基类的实例。然而,事实证明并没有这样的基类或接口。这些元素唯一的共同点是它们有一个getProxy。现在,我在onBootstrap中的代码如下所示:

$sharedEvents->attach('ZfcUser\Form\Register',
                'init',
                function($e) use ($sm)
                {
                    /* @var $form \ZfcUser\Form\Register */
                    $form = $e->getTarget();

                    // Get relevant config
                    $config = $sm->get('config');
                    if ( array_key_exists('redev_user', $config) && is_array($config['redev_user']) )
                    {
                        if ( array_key_exists('custom_fields', $config['redev_user']) && is_array($config['redev_user']['custom_fields']) )
                        {
                            foreach ($config['redev_user']['custom_fields'] as $curCustomField)
                            {
                                $form->add($curCustomField);
                            }
                        }
                    }
[...]
<?php
return array(
    'redev_user' => array(
        'custom_fields' => array(
            // Custom fields which will be added to the registration form
            array(
                    'name' => 'firstname',
                    'type' => 'text',
                    'options' => array(
                            'label' => 'First name',
                    ),
            ),
array(
           'name' => 'country',
           'type' => 'DoctrineModule\Form\Element\ObjectSelect',
           'options' => array(
           'label' => 'Country',
           //'object_manager' => $sm->get('Doctrine\ORM\EntityManager'),
           'target_class'   => 'RedevUser\Entity\Country',
           'property'       => 'countryname',
           'is_method'      => false,
           'find_method'    => array(
               'name'   => 'findBy',
               'params' => array(
                               'criteria' => array(),
                                'orderBy'  => array('countryname' => 'ASC'),
                           ),
            ),
       ),
     ),
foreach ($config['redev_user']['custom_fields'] as $curCustomField)
{
    $formElemFactory = $form->getFormFactory();
    $elem = $formElemFactory->createElement($curCustomField);

    if ($elem instanceof \DoctrineModule\Form\Element\ObjectSelect)
    {
         // Inject ObjectManager
         $elem->getProxy()->setObjectmanager($sm->get('Doctrine\ORM\EntityManager'));
    }

    $form->add($elem);
}

但我并不想检查不同的条令形式元素类型。而且这样做似乎有点脏。关于如何做得更好/更干净,你有什么意见或想法吗?

好吧,不过这就是你必须做的。无法从配置文件中设置EM。使用表单工厂时,必须在元素添加到表单后设置EM。通过遍历所有元素,或者通过了解哪些元素需要EMOkay来感谢您的输入。我想我现在还是坚持这个想法吧。我将把instanceof check改为type check,一次捕获所有的Doctrine表单元素。不是很优雅,但很管用。