user1418998
user1418998

Reputation: 625

Zend FW2 How to use adapter in form class from factories?

My goal is to select distinct records from database table, create array and send it as set of option to select type of form element and also i will need to use same data in form validation in haystack (data same as in options of form element) I thought i will be able to achieve this by creating factory which will return already existing adapter in factories

'adapter' => function($sm) { $dbAdapter= $sm->get('Zend\Db\Adapter\Adapter'); return $dbAdapter ; },

and after in forms and validator classes i planed to use service manager to get this adapter for sql query creation

/*protected $form;*/
protected $adapter;

public function getAdapter()
{
    if (!$this->adapter) {
        $this->adapter = $this->getServiceLocator()
                                  ->get('adapter');
    }

    return $this->adapter;
}

public function getDistinct(){ $sql = "SELECT DISTINCT (lw_folders.f_name), lw_folders.f_id FROM lw_folders INNER JOIN lw_links ON lw_folders.f_id = lw_links.f_id"; return $resultSet = $this->adapter->query($sql);}

But i get a lot of errors, one of them i saying that getServiceLocator() is not found in this form class.

Is my thoughts about usage right? Is there any other way to use custom query to get need records and use them in form class? Thanks for your time!

Upvotes: 0

Views: 177

Answers (2)

AlexP
AlexP

Reputation: 9857

ZF2 makes it very easy to inject class dependencies using factories.

This means that rather than injecting a ServiceLocator into your form you can use it within the factory to fetch the required service and inject that into the constructor instead.

So what does your form class need in order to function?

Firstly change the form __construct to include the array of options for the select list as the form will need these options when you display it.

MyModule\Form\FooForm.php

class FooForm extends Zend\Form\Form
{  
    protected $barOptions = array();

    public function __construct(array $barOptions){
        $this->barOptions = $barOptions; 
    }    

    // Called automatically when we fetch the form from the service locator
    public function init(){

        $this->add(array(
            'name' => 'bar',
            'type' => 'Zend\Form\Element\Select',
            'options' => array(
                'value_options' => $this->barOptions;
            )
        ));
    }
}

Secondly, create a factory to inject these options (where you can use the adapter to fetch them)

MyModule\Form\Factory\FormFactory.php

namespace MyModule\Form\Factory;

use MyModule\Form\FooForm;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;

class FooFormFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $formElementManager)
    {
        $serviceManager = $formElementManager->getServiceLocator();

        $adapter = $serviceManager->get('Zend\Db\Adapter\Adapter');
        $results = $adapter->query('SELECT foo FROM bar');

        $options = array();

        // convert the $results into array $options that the value_options
        // will accept
        // 
        //  $options = array(1 => 'Option 1', 2 => 'Option 2'...)

        return new FooForm($options);
    }
}

Lastly add the service to the module.php file

public function getServiceConfig()
{
    'factories' => array(
        'MyModule\Form\FooForm' => 'MyModule\Form\Factory\FooFormFactory',
    ),
}

The beauty in this approach is that the Form does not care about how the data is loaded, all it needs to know is what the options are and the factory will deal with the loading of them.

You can repeat this same process any other class that requires any other services from the service manager.

Upvotes: 2

dixromos98
dixromos98

Reputation: 754

i think you cannot use the getServiceLocator() inside a form class. But i think i can help with a work around if it can be of any use to you the way Im doing this. inside your form create a function

public function sentadapter($var){

print_r($var);die;
}

and inside a controller where you call your form

$form = $this->getServiceLocator()->get('SomeForm');
$sm = $this->getServiceLocator();
$this->adapter = $sm->get('Zend\Db\Adapter\Adapter');
$form->sentadapter($this->adapter);//with this line you pass the adapter to the form to that function

I don't know if this is helping you. I was able to print the adapter data inside the form class this way. But i don't know if this is the way you would like to use it. Cant think of anything else.

Upvotes: 0

Related Questions