ZF2通过路线形成元素

时间:2015-04-10 11:25:00

标签: php forms routes zend-framework2 element

我正在根据 survey_question_reference 路径值创建一个需要动态选项的表单

'main-surveyquestions'=> [
    'type'    => 'segment',
    'options' => [
        'route'       => '/survey-questions[/:survey_question_reference][/:answer]',
        'constraints' => [
            'survey_question_reference' => '[0-9]*',
            'answer' => '(answer)',
        ],
        'defaults'    => [
            'controller' => 'Main\Controller\Main',
            'action'     => 'surveyquestions'
        ]
    ]
],

这是调用Form

FormElement代码
/**
 * Init
 */
public function init()
{
    /**
     * Survey Answer
     */
    $this->add(
        [
            'type'       => 'Main\Form\Element\SurveyAnswerRadio',
            'name'       => 'survey_answer',
            'options'    => [
                'label' => 'survey_answer'
            ],
            'attributes' => [
                'id' => 'survey_answer'
            ]
        ]
    );
}

以下是表单元素的代码。我有硬编码的地方'sqReference'=> “1” 1 需要替换为路径中 survey_question_reference 的值。

namespace Main\Form\Element;

use Doctrine\ORM\EntityManager;
use Zend\Form\Element\Radio;

/**
 * Class SurveyAnswerRadio
 *
 * @package Main\Form\Element
 */
class SurveyAnswerRadio extends Radio
{
    /**
     * @var EntityManager $entityManager
     */
    protected $entityManager;

    /**
     * @param EntityManager $entityManager
     */
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    /**
     * Get Value Options
     *
     * @return array
     *
     * @throws \Exception
     */
    public function getValueOptions()
    {
        $array = [];

        $result = $this->entityManager
            ->getRepository('AMDatabase\Entity\TheVerse\SA')
            ->findBy(
                [
                    'sqReference' => '1'
                ],
                [
                    'surveyAnswer' => 'ASC'
                ]
            );

        if (is_array($result) && count($result) > '0') {
            /**
             * @var \AMDatabase\Entity\TheVerse\SA $val
             */
            foreach ($result as $val) {
                $array[$val->getReference()] = $val->getSurveyAnswer();
            }
        }

        return $array;
    }
}

2 个答案:

答案 0 :(得分:1)

我建议改变做法。首先,不要试图扩展根本不需要的无线电元素。您可以在表单类中执行相同操作。其次,您的实体管理器也不能在Radio / Form类中工作,直到您的查找机制通过。

所以我建议如下解决方案。

首先将您的表单类注册到module.config.php中的工厂

'form_elements' => array(
    'factories' => array(
         'Main\Form\YourFormName' => function($sm) {
            $form = new Form\YourFormName();
            $form->setEntityManager($sm->getServiceLocator()->get('Doctrine\ORM\EntityManager'));
            $form->setServiceLocator($sm->getServiceLocator());
            return $form;
         },
     ),
),

然后将entityManager和serviceLocator实现到表单类中。

use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class YourFormName extends Form implements ObjectManagerAwareInterface, ServiceLocatorAwareInterface
{
    protected $entityManager;
    protected $serviceLocator;

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
    public function setEntityManager(ObjectManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function getEntityManager()
    {
        return $this->entityManager;
    }

然后在init方法中,您已经初始化了serviceLocator / entityManager。

public function init()
{
    $routeMatch = $this->getServiceLocator()->get('Application')->getMvcEvent()->getRouteMatch();

    $array = [];

    $result = $this->entityManager
        ->getRepository('AMDatabase\Entity\TheVerse\SA')
        ->findBy(
            [
                'sqReference' => $routeMatch->getParam('survey_question_reference')
            ],
            [
                'surveyAnswer' => 'ASC'
            ]
        );

    if (is_array($result) && count($result) > '0') {
        /**
         * @var \AMDatabase\Entity\TheVerse\SA $val
         */
        foreach ($result as $val) {
            $array[$val->getReference()] = $val->getSurveyAnswer();
        }
    }

     $this->add(
    [
        'type'       => 'Zend\Form\Element\Radio',
        'name'       => 'survey_answer',
        'options'    => [
            'label' => 'survey_answer',
            'value_options' => $array,
        ],
        'attributes' => [
            'id' => 'survey_answer',

        ]
    ]
);        

答案 1 :(得分:1)

您需要注意的是<{strong>注入 survey_question_reference参数到您的FormElement。你可以按照@ kuldeep.kamboj的建议在他的答案中做到这一点。但是,如果您不想更改方法并保留自定义SurveyAnswerRadio元素,则必须在代码中进行一些更改:

  1. 使SurveyAnswerRadio实现Zend\ServiceManager\ServiceLocatorAwareInterface,以便您可以实现setServiceLocatorgetServiceLocator,这些是ServiceManager在实例化元素时自动注入服务定位器所必需的。
  2. 您的表单还应实现Zend\ServiceManager\ServiceLocatorAwareInterface
  3. getFormElementConfig
  4. 中实施Module.php方法

    现在让我们看看代码。你会有这样的事情:

    SurveyAnswerRadio:

    class SurveyAnswerRadio extends Radio implements ServiceLocatorAwareInterface
    {
       //Add these two methods
    
       public function setServiceLocator(ServiceLocatorInterface $sl)
       {
          $this->serviceLocator = $sl;
       }
    
       public function getServiceLocator()
       {
          return $this->serviceLocator;
       }
    
       public function getValueOptions()
       {
        $array = [];
        $serviceManager = $this->serviceLocator->getServiceLocator();
        $em = $serviceManager->get('Doctrine\ORM\EntityManager');
        $sqReference = $serviceManager->get('application')->getMvcEvent()
                      ->getRouteMatch()->getParam('survey_question_reference');
    
        $result = $em->getRepository('AMDatabase\Entity\TheVerse\SA')
                     ->findBy(
                            ['sqReference' => $sqReference],
                            ['surveyAnswer' => 'ASC']
                      );
    
        if (is_array($result) && count($result) > '0') {
            foreach ($result as $val) {
                $array[$val->getReference()] = $val->getSurveyAnswer();
            }
        }
    
        return $array;
      }
    }
    

    Module.php:

    按如下方式实施getFormElementConfig方法。这允许使用别名ModuleName\Form\Element\SurveyAnswerRadio实例化或调用类SurveyAnswerRadio

    class Module implements FormElementProviderInterface
    {
    
     // other stuff .....
    
    public function getFormElementConfig()
    {
        return array(
            'invokables' => array(
                'SurveyAnswerRadio' => 'ModuleName\Form\Element\SurveyAnswerRadio'
            )
        );
    }
    }
    

    表单init方法中不需要进行任何更改。

    请注意,在您的控制器中,您必须通过Form实例化FormElementManager

    $formManager = $this->serviceLocator->get('FormElementManager'); 
    $form = $formManager->get('ModuleName\Form\YourForm');
    

    请在documentation

    中查看更多详情

    另请参阅此post,其中介绍了如何在表单中的自定义Select元素中管理依赖项。