Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access Database Adapter in ZF2 Field Set?

I have followed an example and would like to pass the Database adapter to a fieldset to create a drop down menu.

The code below is how i call the fieldset.
How can i access the database adapter in the BrandFieldset class?

$this->add(array(
    'type' => 'Application\Form\BrandFieldset',
    'name' => 'brand',
    'options' => array(
        'label' => 'Brand of the product',
    ),
));
like image 502
Matt Avatar asked Jan 21 '17 17:01

Matt


2 Answers

Instantiating a fieldset is responsibility of the FormElementManager. When you try to access a form, form element or fieldset, the FormElementManager knows where to find and how to create it. This behaviour summerized in Default Services section of the framework.

Since the proper way of accessing form elements is retrieving them from FormElementManager, I would write a BrandFieldsetFactory to inject that DB adapter or further dependencies to fieldset on construction to achieve this.

A ZF3 friendly fieldset factory would look like:

<?php
namespace Application\Form\Factory;

use Application\Form\BrandFieldset;
use Interop\Container\ContainerInterface;

class BrandFieldsetFactory
{
    /**
     * @return BrandFieldset
     */
    public function __invoke(ContainerInterface $fem, $name, array $options = null)
    {
        // FormElementManager is child of AbstractPluginManager 
        // which makes it a ContainerInterface instance
        $adapter = $fem->getServiceLocator()->get('Your\Db\Adapter');
        return new BrandFieldset($adapter);
    }
}

At this point, BrandFieldset should extend the Zend\Form\Fieldset\Fieldset and it's constructor may look like following:

private $dbAdapter;

/**
 * {@inheritdoc}
 */
public function __construct(My/Db/Adapter $db, $options = [])
{
    $this->dbAdapter = $db;
    return parent::__construct('brand-fieldset', $options);
}

Finally, in module.config.php file I'd have a configuration to tell FormElementManager about this factory:

<?php

use Application\Form\BrandFieldset;
use Application\Form\Factory\BrandFieldsetFactory;

return [
    // other config

    // Configuration for form element manager
    'form_elements' => [
        'factories' => [
            BrandFieldset::class => BrandFieldsetFactory::class
        ],
    ],
];

HINT: The BrandFieldset::init() method will be called automatically by FormElementManager after construction. You can put any post-initialization logic into this method.

like image 120
edigu Avatar answered Sep 23 '22 12:09

edigu


Based of these docs I was able to find a solution.

https://framework.zend.com/manual/2.1/en/modules/zend.form.advanced-use-of-forms.html

'form_elements' => array(
    'invokables' => array(
        'fieldset' => BrandFieldsetFactory::class
    )
)

I needed to call the form using the service locator in the controller like below.

$sl = $this->getServiceLocator();
$form = $sl->get('FormElementManager')->get('Application\Form\CreateForm');

In addition I changed the __construct to init.

like image 28
Matt Avatar answered Sep 23 '22 12:09

Matt