Как я могу получить доступ к адаптеру базы данных в поле ZF2 Field Set?

Я последовал примеру и хотел бы передать адаптер базы данных в набор полей, чтобы создать раскрывающееся меню.

Ниже приведен код, как я называю набор полей.
Как я могу получить доступ к адаптеру базы данных в классе BrandFieldset?

$this->add(array(
    'type' => 'Application\Form\BrandFieldset',
    'name' => 'brand',
    'options' => array(
        'label' => 'Brand of the product',
    ),
));

Ответы

Ответ 1

На основе этих документов я смог найти решение.

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

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

Мне нужно было вызвать форму, используя локатор службы в контроллере, как показано ниже.

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

Кроме того, я изменил __construct на init.

Ответ 2

Инициирование набора полей - это FormElementManager. Когда вы пытаетесь получить доступ к форме, элементу формы или набору полей, FormElementManager знает, где найти и как его создать. Это поведение описано в разделе Default Services в разделе.

Поскольку правильный способ доступа к элементам формы извлекает их из FormElementManager, я бы написал BrandFieldsetFactory для добавления этого адаптера БД или дополнительных зависимостей к набору полей для построения для достижения этого.

Приветственное поле типа ZF3 factory будет выглядеть так:

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

В этот момент BrandFieldset должен расширять Zend\Form\Fieldset\Fieldset, и конструктор может выглядеть следующим образом:

private $dbAdapter;

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

Наконец, в файле module.config.php у меня будет конфигурация, чтобы сообщить FormElementManager об этом 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
        ],
    ],
];

СОВЕТ: Метод BrandFieldset::init() будет вызван автоматически FormElementManager после построения. В этот метод можно поместить любую логику после инициализации.