Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend FrameWork 2 Get ServiceLocator In Form and populate a drop down list

I need to get the adapter from the form, but still could not.

In my controller I can recover the adapter using the following:

// 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;
}

In my module I did so:

// 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;
                    },
            ),
    );
}

Could someone give me an example how to get the adapter to the table from the group form?

I have followed this example to my form users: http://framework.zend.com/manual/2.0/en/modules/zend.form.collections.html

EDITED from here...

Maybe I expressed myself wrong to ask the question.

What I really need to do is populate a select (Drop Down) with information from my table groups.

So I need to get the services inside my userForm class by ServiceLocatorAwareInterface (see this link) implemented because By default, the Zend Framework MVC registers an initializer That will inject into the ServiceManager instance ServiceLocatorAwareInterface Implementing any class.

After retrieving the values ​​from the table groups and populate the select.

The problem is that of all the ways that I've tried, the getServiceLocator() returns this:

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

I just wanted to do this in my 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...
like image 397
JulianoMartins Avatar asked Sep 17 '12 12:09

JulianoMartins


3 Answers

The other various answers here generally correct, for ZF < 2.1.

Once 2.1 is out, the framework has a pretty nice solution. This more or less formalizes DrBeza's solution, ie: using an initializer, and then moving any form-bootstrapping into an init() method that is called after all dependencies have been initialized.

I've been playing with the development branch, it it works quite well.

like image 65
timdev Avatar answered Dec 21 '22 05:12

timdev


This is the method I used to get around that issue.

firstly, you want to make your form implement ServiceLocatorInterface as you have done.

You will then still need to manually inject the service locator, and as the whole form is generated inside the contrstuctor you will need to inject via the contructor too (no ideal to build it all in the constructor though)

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;
            },
        ),
    );
}

Now inside your controller you get your form like this:

// Service locator now injected
$form = $this->getServiceLocator()->get('MyModule\Form\MyForm');

Now you will have access to the full service locator inside the form, to get hold of any other services etc such as:

$groups = $this->getServiceLocator()->get('Users\Model\GroupsTable')->fetchAll();
like image 23
Andrew Avatar answered Dec 21 '22 04:12

Andrew


In module.php I create two services. See how I feed the adapter to the form.

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'));
            },

        ),
    );
}

In the form code I use that feed to whatever:

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');
        }

    }
}
like image 25
michaelbn Avatar answered Dec 21 '22 04:12

michaelbn