Zend FrameWork 2 Получить ServiceLocator В форме и заполнить выпадающий список - программирование

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...
4b9b3361

Ответ 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);

И альт, эта работа.