Zend FrameWork 2 Получить ServiceLocator В форме и заполнить выпадающий список
Мне нужно получить адаптер из формы, но все равно не могу.
В моем контроллере я могу восстановить адаптер, используя следующее:
// module/Users/src/Users/Controller/UsersController.php
public function getUsersTable ()
{
if (! $this->usersTable) {
$sm = $this->getServiceLocator();
$this->usersTable = $sm->get('Users\Model\UsersTable');
}
return $this->usersTable;
}
В моем модуле я сделал так:
// module/Users/Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'Users\Model\UsersTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$uTable = new UsersTable($dbAdapter);
return $uTable;
},
//I need to get this to the list of groups
'Users\Model\GroupsTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$gTable = new GroupsTable($dbAdapter);
return $gTable;
},
),
);
}
Может ли кто-нибудь дать мне пример, как получить адаптер в таблицу из групповой формы?
Я воспользовался этим примером для пользователей моей формы:
http://framework.zend.com/manual/2.0/en/modules/zend.form.collections.html
ИЗМЕНИТЬ здесь...
Может быть, я не понял, что задал вопрос.
То, что мне действительно нужно сделать, это заполнить выбор (Drop Down) информацией из моих групп таблиц.
Поэтому мне нужно получить услуги внутри моего класса userForm с помощью ServiceLocatorAwareInterface (см. эту ссылку), поскольку по умолчанию Zend Framework MVC регистрирует инициализатор, который будет вводить в экземпляр ServiceManager ServiceLocatorAwareInterface Внедрение любого класса.
После извлечения значений из групп групп и заполнения выбора.
Проблема в том, что из всех способов, которые я пробовал, getServiceLocator() возвращает это:
Call to a member function get() on a non-object in
D:\WEBSERVER\htdocs\Zend2Control\module\Users\src\Users\Form\UsersForm.php
on line 46
Я просто хотел сделать это в своем UserForm...
namespace Users\Form;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Form\Element;
use Zend\Form\Form;
class UsersForm extends Form implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function getServiceLocator ()
{
return $this->serviceLocator;
}
public function setServiceLocator (ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function __construct ($name = null)
{
parent::__construct('users');
$this->setAttribute('method', 'post');
$sm = $this->getServiceLocator();
$groups = $sm->get('Users\Model\GroupsTable')->fetchAll(); // line 46
$select = new Element\Select('groups');
$options = array();
foreach ($groups as $group) {
$options[$group->id] = $group->name;
}
$select->setValueOptions($options);
$this->add($select);
// and more elements here...
Ответы
Ответ 1
Другие различные ответы здесь в целом правильны, поскольку ZF < 2.1.
Как только 2.1 выйдет, структура имеет красивое хорошее решение. Это более или менее формализует решение DrBeza, то есть: использует инициализатор, а затем перемещает любую форму-загрузку в метод init(), который вызывается после инициализации всех зависимостей.
Я играл с ветвью разработки, она работает хорошо.
Ответ 2
Это метод, который я использовал для решения этой проблемы.
во-первых, вы хотите, чтобы ваша форма реализовала ServiceLocatorInterface, как вы это сделали.
Затем вам все равно придется вручную вводить локатор сервисов, и поскольку вся форма создается внутри contrstuctor, вам также нужно будет вводить через конструктора (нет идеала, чтобы все это построить в конструкторе)
module.php
/**
* Get the service Config
*
* @return array
*/
public function getServiceConfig()
{
return array(
'factories' => array(
/**
* Inject ServiceLocator into our Form
*/
'MyModule\Form\MyForm' => function($sm) {
$form = new \MyModule\Form\MyFormForm('formname', $sm);
//$form->setServiceLocator($sm);
// Alternativly you can inject the adapter/gateway directly
// just add a setter on your form object...
//$form->setAdapter($sm->get('Users\Model\GroupsTable'));
return $form;
},
),
);
}
Теперь внутри вашего контроллера вы получите свою форму следующим образом:
// Service locator now injected
$form = $this->getServiceLocator()->get('MyModule\Form\MyForm');
Теперь у вас будет доступ к полному локатору службы внутри формы, чтобы получить доступ к другим сервисам и т.д., например:
$groups = $this->getServiceLocator()->get('Users\Model\GroupsTable')->fetchAll();
Ответ 3
В module.php создаю две службы. Посмотрите, как я подключаю адаптер к форме.
public function getServiceConfig()
{
return array(
'factories' => array(
'db_adapter' => function($sm) {
$config = $sm->get('Configuration');
$dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
return $dbAdapter;
},
'my_amazing_form' => function ($sm) {
return new \dir\Form\SomeForm($sm->get('db_adapter'));
},
),
);
}
В коде формы я использую этот канал для чего-либо:
namespace ....\Form;
use Zend\Form\Factory as FormFactory;
use Zend\Form\Form;
class SomeForm extends Form
{
public function __construct($adapter, $name = null)
{
parent::__construct($name);
$factory = new FormFactory();
if (null === $name) {
$this->setName('whatever');
}
}
}
Ответ 4
Мы обрабатываем это в модели, добавляя метод, который принимает форму
public function buildFormSelectOptions($form, $context = null)
{
/**
* Do this this for each form element that needs options added
*/
$model = $this->getServiceManager()->get('modelProject');
if (empty($context)){
$optionRecords = $model->findAll();
} else {
/**
* other logic for $optionRecords
*/
}
$options = array('value'=>'', 'label'=>'Choose a Project');
foreach ($optionRecords as $option) {
$options[] = array('value'=>$option->getId(), 'label'=>$option->getName());
}
$form->get('project')->setAttribute('options', $options);
}
Поскольку форма передается по ссылке, мы можем сделать что-то подобное в контроллере, где построена форма:
$builder = new AnnotationBuilder();
$form = $builder->createForm($myEntity);
$myModel->buildFormSelectOptions($form, $myEntity);
$form->add(array(
'name' => 'submitbutton',
'attributes' => array(
'type' => 'submit',
'value' => 'Submit',
'id' => 'submitbutton',
),
));
$form->add(array(
'name' => 'cancel',
'attributes' => array(
'type' => 'submit',
'value' => 'Cancel',
'id' => 'cancel',
),
));
Примечание. В примере предполагается, что базовая форма создается через аннотации, но не имеет значения, как вы создаете исходную форму.
Ответ 5
Альтернативным методом для других ответов было бы создать Инициализатор ServiceManager.
Примером существующего инициализатора является способ ввода ServiceManager, если ваш экземпляр реализует ServiceLocatorAwareInterface.
Идея заключалась бы в создании интерфейса, который вы проверяете в своем Инициализаторе, этот интерфейс может выглядеть так:
interface FormServiceAwareInterface
{
public function init();
public function setServiceManager(ServiceManager $serviceManager);
}
Пример того, как выглядит ваш Инициализатор:
class FormInitializer implements InitializerInterface
{
public function initialize($instance, ServiceLocatorInterface $serviceLocator)
{
if (!$instance instanceof FormServiceAwareInterface)
{
return;
}
$instance->setServiceManager($serviceLocator);
$instance->init();
}
}
Все, что происходит в init()
, будет иметь доступ к ServiceManager
. Конечно, вам нужно добавить свой инициализатор в конфигурацию SM.
Это не идеально, но он отлично подходит для моих нужд и может также применяться к любым Fieldsets, выведенным из ServiceManager.
Ответ 6
Вот как я использовал эту проблему.
во-первых, в Module.php создайте службу (как и вы сделали):
// module/Users/Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'Users\Model\UsersTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$uTable = new UsersTable($dbAdapter);
return $uTable;
},
//I need to get this to the list of groups
'Users\Model\GroupsTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$gTable = new GroupsTable($dbAdapter);
return $gTable;
},
),
);
}
Затем в контроллере я получил ссылку на Сервис:
$users = $this->getServiceLocator()->get('Test\Model\TestGroupTable')->fetchAll();
$options = array();
foreach ($users as $user)
$options[$user->id] = $user->name;
//get the form element
$form->get('user_id')->setValueOptions($options);
И альт, эта работа.