Zend Framework 2: passing variables (“options”) to

2019-07-20 01:21发布

问题:

I need to programmatically change the behaviour of a form based on some options. Let's say, for example, I'm displaying a form with some user's info.

I need to display a checkbox, "send mail", if and only if a user has not received an activation mail yet. Previously, with ZF1, i used to do something like

$form = new MyForm(array("displaySendMail" => true))

which, in turn, was received as an option, and which allow'd to do

class MyForm extends Zend_Form {

    protected $displaySendMail;

    [...]

    public function setDisplaySendMail($displaySendMail)
    {
        $this->displaySendMail = $displaySendMail;
    }


    public function init() {
        [....]
        if($this->displaySendMail)
        {
            $displaySendMail  new Zend_Form_Element_Checkbox("sendmail");
            $displaySendMail
                   ->setRequired(true)
                   ->setLabel("Send Activation Mail");
        }
    }

How could this be accomplished using Zend Framework 2? All the stuff I found is about managing dependencies (classes), and nothing about this scenario, except this SO question: ZF2 How to pass a variable to a form which, in the end, falls back on passing a dependency. Maybe what's on the last comment, by Jean Paul Rumeau could provide a solution, but I wasn't able to get it work. Thx A.

@AlexP, thanks for your support. I already use the FormElementManager, so it should be straightforward. If I understand correctly, I should just retrieve these option in my SomeForm constructor, shouldn't I?

[in Module.php]

'Application\SomeForm' => function($sm)
           {
                $form = new SomeForm();
                $form->setServiceManager($sm);
                return $form;
            },

while in SomeForm.php

class SomeForm extends Form implements ServiceManagerAwareInterface
{
    protected $sm;

    public function __construct($name, $options) {
         [here i have options?]
         parent::__construct($name, $options);
    }
 }

I tryed this, but was not working, I'll give it a second try and double check everything.

回答1:

With the plugin managers (classes extending Zend\ServiceManager\AbstractPluginManager) you are able to provide 'creation options' array as the second parameter.

$formElementManager = $serviceManager->get('FormElementManager');
$form = $formElementManager->get('SomeForm', array('foo' => 'bar')); 

What is important is how you have registered the service with the manager. 'invokable' services will have the options array passed into the requested service's constructor, however 'factories' (which have to be a string of the factory class name) will get the options in it's constructor.

Edit

You have registered your service with an anonymous function which mean this will not work for you. Instead use a factory class.

// Module.php
public function getFormElementConfig()
{
    return array(
        'factories' => array(
            'Application\SomeForm' => 'Application\SomeFormFactory',
        ),
    );
}

An then it's the factory that will get the options injected into it's constructor (which if you think about it makes sense).

namespace Application;

use Application\SomeForm;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;

class SomeFormFactory implements FactoryInterface
{
    protected $options = array();

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

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return new SomeForm('some_form', $this->options);
    }
}

Alternatively, you can inject directly into the service you are requesting (SomeForm) by registering it as an 'invokeable' service; obviously this will depend on what dependencies the service requires.