我正在根据 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;
}
}
答案 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
元素,则必须在代码中进行一些更改:
SurveyAnswerRadio
实现Zend\ServiceManager\ServiceLocatorAwareInterface
,以便您可以实现setServiceLocator
和getServiceLocator
,这些是ServiceManager在实例化元素时自动注入服务定位器所必需的。 Zend\ServiceManager\ServiceLocatorAwareInterface
。getFormElementConfig
。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');
中查看更多详情
另请参阅此post,其中介绍了如何在表单中的自定义Select
元素中管理依赖项。