diff --git a/docs/book/index.md b/docs/book/index.md deleted file mode 120000 index fe8400541..000000000 --- a/docs/book/index.md +++ /dev/null @@ -1 +0,0 @@ -../../README.md \ No newline at end of file diff --git a/docs/book/index.md b/docs/book/index.md new file mode 100644 index 000000000..b8c87cfac --- /dev/null +++ b/docs/book/index.md @@ -0,0 +1,21 @@ +## Installation + +### Using Composer + +```bash +$ composer require laminas/laminas-form +``` + +## Learn + +
+namespace Album;
+
+use Laminas\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory;
+
+return [
+ 'controllers' => [
+ 'factories' => [
+ // Add this line
+ Controller\AlbumController::class => ReflectionBasedAbstractFactory::class,
+ ],
+ ],
+ // …
+];
+
+
+## Fetch a Form without Registration
+
+The following example creates a form class:
+
+```php
+final class AlbumForm extends Laminas\Form\Form
+{
+ public function init(): void
+ {
+ // …
+ }
+}
+```
+
+Extend the controller and fetch the form:
+
+
+namespace Album\Controller;
+
+use Album\Form\AlbumForm;
+use Laminas\Form\FormElementManager;
+use Laminas\Mvc\Controller\AbstractActionController;
+
+use function assert;
+
+final class AlbumController extends AbstractActionController
+{
+ public function __construct(
+ public readonly FormElementManager $formElementManager
+ ) {}
+
+ public function addAction()
+ {
+ $form = $this->formElementManager->get(AlbumForm::class);
+ assert($form instanceof AlbumForm);
+
+ // …
+ }
+}
+
+
+## Register and Fetch a Form With a Factory
+
+If a form needs some preparation for creation then a factory can be used.
+
+The following example creates a factory class for the form:
+
+```php
+final class AlbumFormFactory
+{
+ public function __invoke(Psr\Container\ContainerInterface): AlbumForm
+ {
+ $form = new AlbumForm();
+ $form->setName('album');
+
+ return $form;
+ }
+}
+```
+
+Register the form on the form element manager via the configuration key `form_elements` in the module configuration, e.g. `module/Album/config/module.config.php`:
+
+
+namespace Album;
+
+return [
+ 'form_elements' => [
+ 'factories' => [
+ // Add this line
+ Form\AlbumForm::class => Form\AlbumFormFactory::class,
+ ],
+ ],
+ // …
+];
+
+
+To retrieve the form and the form name in a controller:
+
+```php
+namespace Album\Controller;
+
+use Album\Form\AlbumForm;
+use Laminas\Form\FormElementManager;
+use Laminas\Mvc\Controller\AbstractActionController;
+
+use function assert;
+
+final class AlbumController extends AbstractActionController
+{
+ // …
+
+ public function addAction()
+ {
+ $form = $this->formElementManager->get(AlbumForm::class);
+ assert($form instanceof AlbumForm);
+
+ echo $form->getName(); // album
+
+ // …
+ }
+}
+```
+
+Now the custom factory will be used to create the form instance.
+
+## Using a Custom Element without Registration
+
+The form element manager [allows fetching custom elements without prior registration](../form-element-manager.md#usage-of-the-form-element-manager-in-a-form) with the manager.
+
+The following example creates a custom element:
+
+```php
+final class ExampleElement extends Laminas\Form\Element
+{
+ // …
+}
+```
+
+Create a form and add the custom element:
+
+```php
+final class ExampleForm extends Laminas\Form\Form
+{
+ public function init(): void
+ {
+ $this->add([
+ 'type' => ExampleElement::class,
+ 'name' => 'example',
+ 'options' => [
+ 'label' => 'Example element'
+ ],
+ ]);
+
+ // …
+ }
+}
+```
+
+Fetch the form and the element in a controller:
+
+```php
+namespace Album\Controller;
+
+use Album\Form\AlbumForm;
+use Laminas\Form\FormElementManager;
+use Laminas\Mvc\Controller\AbstractActionController;
+
+use function assert;
+
+final class AlbumController extends AbstractActionController
+{
+ // …
+
+ public function addAction()
+ {
+ $form = $this->formElementManager->get(AlbumForm::class);
+ assert($form instanceof AlbumForm);
+
+ echo $form->get('example')->getLabel(); // Example element
+
+ // …
+ }
+}
+```
+
+## Register and Use a Custom Element via a Factory
+
+If a custom element needs some preparation for creation then a factory can be used.
+
+The following example creates a factory class for the element of the previous example:
+
+```php
+final class ExampleElementFactory
+{
+ public function __invoke(Psr\Container\ContainerInterface): ExampleElement
+ {
+ $element = new ExampleElement();
+ $element->setOption('example_param', 'value');
+
+ return $element;
+ }
+}
+```
+
+Register the element on the form element manager via the configuration key `form_elements` in the module configuration, e.g. `module/Album/config/module.config.php`:
+
+
+namespace Album;
+
+return [
+ 'form_elements' => [
+ 'factories' => [
+ // Add this line
+ Form\ExampleElement::class => Form\ExampleElementFactory::class,
+ ],
+ ],
+ // …
+];
+
+
+Now the custom factory will be used to create the element instance.
+
+## Configuring the Form Element Manager
+
+The [configuration of the form element manager follows the exact same pattern](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/) as for a normal service manager of laminas-servicemanager.
+
+In a laminas-mvc based application this means using the application or module configuration, such as `config/autload/global.php` or `module/Album/config/module.config.php`, and the configuration key `form_elements`:
+
+```php
+return [
+ 'form_elements' => [
+ 'factories' => [
+ Album\Form\ExampleElement::class => Album\Form\ExampleElementFactory::class,
+ ],
+ 'aliases' => [
+ 'example' => Album\Form\ExampleElement::class,
+ ],
+ 'abstract_factories' => [],
+ 'delegators' => [],
+ // …
+ ]
+];
+```
+
+The factory `Laminas\Form\FormElementManagerFactory` uses the configuration, searches for the configuration key `form_elements` and creates the form element manager using the discovered configuration.
+
+## Learn More
+
+- [The basics of the form element manager](../form-element-manager.md)
+- [Creating custom elements](../advanced.md#creating-custom-elements)
+- [Handling dependencies](../advanced.md#handling-dependencies)
+- [Configuring the service manager](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/)
diff --git a/docs/book/v3/form-element-manager.md b/docs/book/v3/form-element-manager.md
new file mode 100644
index 000000000..0aee00bcb
--- /dev/null
+++ b/docs/book/v3/form-element-manager.md
@@ -0,0 +1,318 @@
+# Form Element Manager
+
+The form element manager is a *specialized* dependency injection container to obtain objects which implements the `Laminas\Form\ElementInterface` interface.
+
+The manager is the central object of laminas-form to create and retrieve all types of form elements, fieldsets and forms.
+
+It handles all included form elements of laminas-form, user-defined elements and also whole forms.
+
+The manager is based on the [plugin manager of laminas-servicemanager](https://docs.laminas.dev/laminas-servicemanager/plugin-managers/).
+
+## Benefits
+
+The following benefits are provided by the manager:
+
+- Handles all forms, fieldsets and elements, including all custom ones.
+- Create forms, fieldsets and elements with all dependencies like validators and filters.
+- Can create forms, fieldsets and elements with name and options.
+- Can provide elements, fieldsets and forms without prior registration.
+- Fetches hydrators and input filters from the application's service container and adds them to a form or a fieldset.
+- Allows overriding existing elements or extending them.
+
+> INFO: **Stand-Alone Usage**
+> The following examples show the basics of the form element manager using stand-alone usage.
+>
+> The configuration and usage in **laminas-mvc** or **Mezzio** based application [can be found in separate sections](#learn-more).
+
+## Create a Form Element Manager
+
+To create an instance, the form element manager requires a [PSR-11 dependency container](https://www.php-fig.org/psr/psr-11/).
+The following examples use the PSR-11 container implementation provided by [laminas-servicemanager](https://docs.laminas.dev/laminas-servicemanager/):
+
+```php
+$formElementManager = new Laminas\Form\FormElementManager(
+ new Laminas\ServiceManager\ServiceManager()
+);
+```
+
+## Fetch a Standard Element
+
+To get a supplied form element, use the class name of the element:
+
+```php
+$element = $formElementManager->get(Laminas\Form\Element\Select::class);
+```
+
+## Fetch and Configure a Standard Element
+
+The form element manager uses the factory `Laminas\Form\ElementFactory` to create all elements, fieldsets, and forms.
+This factory allows the configuration of an element during fetching:
+
+```php
+$element = $formElementManager->get(
+ Laminas\Form\Element\Select::class,
+ [
+ 'name' => 'rating',
+ 'options' => [
+ 'label' => 'Rating',
+ 'value_options' => [1, 2, 3, 4, 5],
+ ],
+ ],
+ ]
+);
+```
+
+The name for the element and the options array are provided as parameters to the associated class constructor on instantiation:
+
+```php
+public function __construct($name = null, iterable $options = []) {}
+```
+
+Retrieving the name and the set options:
+
+```php
+echo $element->getName(); // rating
+echo $element->getLabel(); // Rating
+
+$valueOptions = $element->getValueOptions(); // [1, 2, 3, 4, 5]
+```
+
+## Fetch a Custom Element without Registration
+
+The form element manager allows fetching custom elements without prior registration with the manager.
+
+The following example creates a custom element:
+
+```php
+final class ExampleElement extends Laminas\Form\Element
+{
+ // …
+}
+```
+
+The form element manager can create these custom elements by the related class name:
+
+```php
+$element = $formElementManager->get(ExampleElement::class);
+```
+
+The manager uses the factory `Laminas\Form\ElementFactory` to instantiate the element, and will pass the name and options array just like in the prior example:
+
+```php
+$element = $formElementManager->get(
+ ExampleElement::class,
+ [
+ 'name' => '…',
+ 'options' => [
+ // …
+ ],
+ ]
+);
+```
+
+## Register and Fetch a Custom Element with a Factory
+
+If a custom element needs some preparation for creation then a factory can be used.
+
+The following example creates a factory class for the element:
+
+```php
+final class ExampleElementFactory
+{
+ public function __invoke(Psr\Container\ContainerInterface): ExampleElement
+ {
+ $element = new ExampleElement();
+ $element->setOption('example_param', 'value');
+
+ return $element;
+ }
+}
+```
+
+Register the custom element on the form element manager by using a factory class:
+
+```php
+$formElementManager->setFactory(
+ ExampleElement::class,
+ ExampleElementFactory::class
+);
+```
+
+Get the custom element and the option:
+
+```php
+$element = $formElementManager->get(ExampleElement::class);
+
+echo $form->getOption('example_param'); // value
+```
+
+Now the custom factory will be used to create the element instance.
+
+## Fetch a Form without Registration
+
+The form element manager also handles whole forms.
+
+The following example creates a form class:
+
+```php
+final class ExampleForm extends Laminas\Form\Form
+{
+ public function init(): void
+ {
+ // …
+ }
+}
+```
+
+The form element manager can create the form by the related class name:
+
+```php
+$form = $formElementManager->get(ExampleForm::class);
+```
+
+If no separate factory is required, then the form element manager will be instantiating the form class directly, by using the standard factory for elements (`Laminas\Form\ElementFactory`).
+
+## Register and Fetch a Form With a Factory
+
+If a form needs some preparation for creation then a factory can be used.
+
+The following example creates a class as factory for the form:
+
+```php
+final class ExampleFormFactory
+{
+ public function __invoke(Psr\Container\ContainerInterface): ExampleForm
+ {
+ $form = new ExampleForm();
+ $form->setName('example');
+
+ return $form;
+ }
+}
+```
+
+Register the form on the form element manager by using a factory class:
+
+```php
+$formElementManager->setFactory(
+ ExampleForm::class,
+ ExampleFormFactory::class
+);
+```
+
+Get the form and the name:
+
+```php
+$form = $formElementManager->get(ExampleForm::class);
+
+echo $form->getName(); // example
+```
+
+Now the custom factory will be used to instantiate the form.
+
+## Set a Paramater to a Form on Instantiation
+
+The options of a form can be used to set custom parameters to a form.
+
+- It can be hooked into the initialization via the `init()` method.
+- The form element factory calls the `init()` method after creating an instance of the class.
+- Since the name and options are processed in the constructor, it can access them within `init()` to perform further customization of the instance.
+
+Create a class for the form and get a custom option:
+
+```php
+final class ExampleForm extends Laminas\Form\Form
+{
+ public function init(): void
+ {
+ /** @var mixed|null $exampleParam */
+ $exampleParam = $this->getOption('example_param');
+
+ // …
+ }
+}
+```
+
+The standard factory `Laminas\Form\ElementFactory` for form elements and forms is used which provides the name and/or the options to the object as arguments to the constructor:
+
+```php
+$form = $formElementManager->get(
+ ExampleForm::class,
+ [
+ 'options' => [
+ 'example_param' => 'value',
+ ],
+ ]
+);
+
+echo $form->getOption('example_param'); // value
+```
+
+## Usage of the Form Element Manager in a Form
+
+If an element is added to a form via the `add` method and the definition of the element is provided via an array then the form factory `Laminas\Form\Factory` will be used to create this element.
+The form factory uses the form element manager to fetch the element.
+The following example uses a custom element in a form:
+
+```php
+final class ExampleForm extends Laminas\Form\Form
+{
+ public function init(): void
+ {
+ $this->add([
+ 'type' => ExampleElement::class,
+ 'name' => 'example',
+ 'options' => [
+ 'label' => 'Example element'
+ ],
+ ]);
+
+ // …
+ }
+}
+```
+
+Fetch the form and the element:
+
+```php
+$form = $formElementManager->get(ExampleForm::class);
+
+echo $form->get('example')->getLabel(); // Example element
+```
+
+The form element manager will provide the form with the custom element which is created by the form element manager, like before: with or without explicit registration of the element.
+
+## Configuring the Form Element Manager
+
+The manager is based on the [plugin manager of laminas-servicemanager](https://docs.laminas.dev/laminas-servicemanager/plugin-managers/) and the [configuration follows the exact same pattern](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/) as for a normal service manager of laminas-servicemanager:
+
+```php
+$formElementManager = new Laminas\Form\FormElementManager(
+ new Laminas\ServiceManager\ServiceManager(),
+ [
+ 'factories' => [
+ Album\Form\ExampleElement::class => Album\Form\ExampleElementFactory::class,
+ ],
+ 'aliases' => [
+ 'example' => Album\Form\ExampleElement::class,
+ ],
+ 'abstract_factories' => [],
+ 'delegators' => [],
+ // …
+ ]
+);
+```
+
+## Why Use the Form Element Manager?
+
+- It allows overwriting or extending elements without changing form specifications.
+- It allows decoration of elements, like adding a database adapter without passing the adapter through all layers of a form.
+- It manages instantiation and initialization of elements, fieldsets and forms, including all dependencies and configuration options.
+- It allows usage and configuration of custom elements without prior registration of the elements.
+- It handles all form object types: elements, fieldsets and the form itself.
+
+## Learn More
+
+- [Usage of Form Element Manager in a laminas-mvc Application](application-integration/form-element-manager-mvc.md)
+- [The `init` method](advanced.md#initialization)
+- [Configuring the service manager](https://docs.laminas.dev/laminas-servicemanager/configuring-the-service-manager/)
diff --git a/mkdocs.yml b/mkdocs.yml
index f6b92ab1c..4f7b9bd61 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -11,6 +11,7 @@ nav:
- "Creation via Factory": v3/form-creation/creation-via-factory.md
- "Factory-Backed Form Extension": v3/form-creation/factory-backed-form-extension.md
- "Using PHP8 Attributes or DocBlock Annotations": v3/form-creation/attributes-or-annotations.md
+ - "Form Element Manager": v3/form-element-manager.md
- Elements:
- Introduction: v3/element/intro.md
- Element: v3/element/element.md
@@ -91,6 +92,7 @@ nav:
- "Advanced Use Cases": v3/advanced.md
- "Application Integration":
- "Usage in a laminas-mvc application": v3/application-integration/usage-in-a-laminas-mvc-application.md
+ - "Usage of Form Element Manager in a laminas-mvc Application": v3/application-integration/form-element-manager-mvc.md
- Migration:
- "Migration from Version 2 to 3": v3/migration/v2-to-v3.md
- v2:
@@ -189,6 +191,7 @@ extra:
installation:
config_provider_class: 'Laminas\Form\ConfigProvider'
module_class: 'Laminas\Form\Module'
+ show_special_homepage: true
plugins:
- search
- redirects: