Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Ability to get an element with creation options from the FormElementManager #4400

Closed
wants to merge 2 commits into from

4 participants

@noopable

Now we can get an element from the FormElementManager with only name.

$element = $FormElementManager->get('element', 'foo');
echo $element->getName();// foo

It is inconvenient not to have the 2nd parameter, 'options'.

@vadexito

would be also great to have the options parameter when we use
$form->add([
'type' => 'Element\Class'
'options' => $someOptions
]);

it seems also to be instantiated by the formelementmanager without the options parameter....

@noopable

Yes, it is available.
But I said about FormElementManager's capability.
Sometimes, the FormElementManager is a gateway to get a customized form with creationOptions. And this is AbstractPluginManager's normal behavior.

$form = $formManager->get('Application/Form/Contact', $someOptions);

And so, the first parameter of FormElementManager::get is the name representing an instance. If we want to use class type, set it to Invokable or set the serviceConfig or set the di alias .
Invokable enables us to create an instance in simple use.
And new FormAbstractServiceFactory enables us to create a form with the serviceConfig.
And the di enables us to compose the form elements by di configuration.

But now the FormElementManager drops options for invokale.This PR will fix it.

@danizord

@noopable That's why we have the Zend\Form\Factory.

@noopable

@Danizord
Thanks.
Can you tell me why AbstractPluginManager::get accept the 2nd parameter as CreationOptions?
Why does the FormPluginManager drop creationOptions though we cannot set even a label through it?
Is it just because there is factory?

@weierophinney

Why does the FormPluginManager drop creationOptions though we cannot set even a label through it?

It doesn't, though. If you write a custom factory, you will get the options; they will also be passed to invokables. That said, I think your approach makes a lot of sense, considering that the constructor for all objects under Zend\Form use $name as the first argument.

@weierophinney

Merged to develop for release with 2.3, as it's a minor behavior change.

@noopable noopable deleted the noopable:patch-FormElementManager-withParams branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
58 library/Zend/Form/FormElementManager.php
@@ -123,4 +123,62 @@ public function validatePlugin($plugin)
(is_object($plugin) ? get_class($plugin) : gettype($plugin))
));
}
+
+ /**
+ * Retrieve a service from the manager by name
+ *
+ * Allows passing an array of options to use when creating the instance.
+ * createFromInvokable() will use these and pass them to the instance
+ * constructor if not null and a non-empty array.
+ *
+ * @param string $name
+ * @param string|array $options
+ * @param bool $usePeeringServiceManagers
+ * @return object
+ */
+ public function get($name, $options = array(), $usePeeringServiceManagers = true)
+ {
+ if (is_string($options)) {
+ $options = array('name' => $options);
+ }
+ return parent::get($name, $options, $usePeeringServiceManagers);
+ }
+
+ /**
+ * Attempt to create an instance via an invokable class
+ *
+ * Overrides parent implementation by passing $creationOptions to the
+ * constructor, if non-null.
+ *
+ * @param string $canonicalName
+ * @param string $requestedName
+ * @return null|\stdClass
+ * @throws Exception\ServiceNotCreatedException If resolved class does not exist
+ */
+ protected function createFromInvokable($canonicalName, $requestedName)
+ {
+ $invokable = $this->invokableClasses[$canonicalName];
+
+ if (null === $this->creationOptions
+ || (is_array($this->creationOptions) && empty($this->creationOptions))
+ ) {
+ $instance = new $invokable();
+ } else {
+ if (isset($this->creationOptions['name'])) {
+ $name = $this->creationOptions['name'];
+ } else {
+ $name = $requestedName;
+ }
+
+ if (isset($this->creationOptions['options'])) {
+ $options = $this->creationOptions['options'];
+ } else {
+ $options = $this->creationOptions;
+ }
+
+ $instance = new $invokable($name, $options);
+ }
+
+ return $instance;
+ }
}
View
42 tests/ZendTest/Form/FormElementManagerTest.php
@@ -67,4 +67,46 @@ public function testLoadingInvalidElementRaisesException()
$this->setExpectedException('Zend\Form\Exception\InvalidElementException');
$this->manager->get('test');
}
+
+ public function testStringCreationOptions()
+ {
+ $args = 'foo';
+ $element = $this->manager->get('element', $args);
+ $this->assertEquals('foo', $element->getName(), 'The argument is string');
+ }
+
+ public function testArrayCreationOptions()
+ {
+ $args = array(
+ 'name' => 'foo',
+ 'options' => array(
+ 'label' => 'bar'
+ ),
+ );
+ $element = $this->manager->get('element', $args);
+ $this->assertEquals('foo', $element->getName(), 'Specified name in array[name]');
+ $this->assertEquals('bar', $element->getLabel(), 'Specified options in array[options]');
+ }
+
+ public function testOptionsCreationOptions()
+ {
+ $args = array(
+ 'label' => 'bar'
+ );
+ $element = $this->manager->get('element', $args);
+ $this->assertEquals('element', $element->getName(), 'Invokable CNAME');
+ $this->assertEquals('bar', $element->getLabel(), 'Specified options in array');
+ }
+
+ public function testArrayOptionsCreationOptions()
+ {
+ $args = array(
+ 'options' => array(
+ 'label' => 'bar'
+ ),
+ );
+ $element = $this->manager->get('element', $args);
+ $this->assertEquals('element', $element->getName(), 'Invokable CNAME');
+ $this->assertEquals('bar', $element->getLabel(), 'Specified options in array[options]');
+ }
}
Something went wrong with that request. Please try again.