This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
Go to file
Fabien Potencier d3fac8600c feature #27291 [OptionsResolver] Added support for nesting options definition (yceruto)
This PR was merged into the 4.2-dev branch.

Discussion
----------

[OptionsResolver] Added support for nesting options definition

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #4833
| License       | MIT
| Doc PR        | https://github.com/symfony/symfony-docs/pull/9995

I'd like to propose an alternative to #27251 and #18134 with a different approach.

It would allow you to create a nested options system with required options, validation (type, value),
normalization and more.

<details>
 <summary><strong>Short documentation</strong></summary>

**To define a nested option, you can pass a closure as the default value of the option with an `OptionsResolver` argument:**
```php
$resolver
    ->defaults([
        'connection' => 'default',
        'database' => function (OptionsResolver $resolver) {
            $resolver
                ->setRequired(['dbname', 'host', ...])
                ->setDefaults([
                    'driver' => 'pdo_sqlite',
                    'port' => function (Options $options) {
                        return 'pdo_mysql' === $options['driver'] ? 3306 : null,
                    },
                    'logging' => true,
                ])
                ->setAllowedValues('driver', ['pdo_sqlite', 'pdo_mysql'])
                ->setAllowedTypes('port', 'int')
                ->setAllowedTypes('logging', 'bool')
                // ...
        },
    ]);

$resolver->resolve(array(
    'database' => array(
        'dbname' => 'demo',
        'host' => 'localhost',
        'driver' => 'pdo_mysql',
    ),
));

// returns: array(
//    'connection' => 'default',
//    'database' => array(
//        'dbname' => 'demo',
//        'host' => 'localhost',
//        'driver' => 'pdo_mysql',
//        'port' => 3306,
//        'logging' => true,
//    ),
//)
```
Based on this instance, you can define the options under ``database`` and its desired default
value.

**If the default value of a child option depend on another option defined in parent level,
adds a second ``Options`` argument to the closure:**
```php
$resolver
    ->defaults([
        'profiling' => false,
        'database' => function (OptionsResolver $resolver, Options $parent) {
            $resolver
                ->setDefault('logging', $parent['profiling'])
                ->setAllowedTypes('logging', 'bool');
        },
    ])
;
```
**Access to nested options from lazy or normalize functions in parent level:**
```php
$resolver
    ->defaults([
        'version' => function (Options $options) {
            return $options['database']['server_version'];
        },
        'database' => function (OptionsResolver $resolver) {
            $resolver
                ->setDefault('server_version', 3.15)
                ->setAllowedTypes('server_version', 'numeric')
                // ...
        },
    ])
;
```
As condition, for nested options you must to pass an array of values to resolve it on runtime, otherwise an exception will be thrown:
```php
$resolver->resolve(); // OK
$resolver->resolve(['database' => []]); // OK
$resolver->resolve(['database' => null); // KO (Exception!)
```
</details>

---

Demo app https://github.com/yceruto/nested-optionsresolver-demo

Commits
-------

d04e40be5a Added support for nested options definition
2018-10-10 04:11:23 -07:00
.composer Drop hirak/prestissimo 2016-05-12 07:44:15 -05:00
.github Merge branch '4.1' 2018-09-05 14:00:05 +02:00
src/Symfony feature #27291 [OptionsResolver] Added support for nesting options definition (yceruto) 2018-10-10 04:11:23 -07:00
.appveyor.yml Merge branch '4.1' 2018-09-05 14:00:05 +02:00
.editorconfig Update .editorconfig 2018-09-06 16:22:56 +02:00
.gitignore Add appveyor.yml for C.I. on Windows 2015-08-25 23:41:37 +02:00
.php_cs.dist Merge branch '4.1' 2018-10-02 14:43:31 +02:00
.travis.yml Add new Zookeeper Data Store. Add functional test for Zookeeper Data Store. Modify Store Factory to support initialization of Zookeeper Data Store. 2018-09-20 09:05:24 +02:00
CHANGELOG-4.0.md Merge branch '3.4' into 4.1 2018-08-01 18:22:14 +02:00
CHANGELOG-4.1.md updated CHANGELOG for 4.1.5 2018-09-30 07:05:30 +02:00
composer.json [Cache] leverage Contracts\Cache 2018-09-04 09:24:06 +02:00
CONTRIBUTING.md Mention the community review guide 2016-12-18 22:02:35 +01:00
CONTRIBUTORS.md update CONTRIBUTORS for 2.8.46 2018-09-30 05:52:49 +02:00
LICENSE fixed years in copyright 2018-01-03 08:23:28 +01:00
link appending root of Contracts dir (where composer.json is located) 2018-07-31 21:19:26 +03:00
phpunit Default testsuite to latest PHPUnit 6.* 2018-05-25 15:04:04 +02:00
phpunit.xml.dist Add new Zookeeper Data Store. Add functional test for Zookeeper Data Store. Modify Store Factory to support initialization of Zookeeper Data Store. 2018-09-20 09:05:24 +02:00
README.md Merge branch '2.8' into 3.4 2018-05-25 16:50:57 +02:00
UPGRADE-4.0.md Merge branch '2.8' into 3.4 2018-05-31 12:13:22 +02:00
UPGRADE-4.1.md Merge branch '4.0' into 4.1 2018-05-31 12:17:53 +02:00
UPGRADE-4.2.md simplify the form type extension registration 2018-10-08 23:29:09 +02:00
UPGRADE-5.0.md simplify the form type extension registration 2018-10-08 23:29:09 +02:00

Symfony is a PHP framework for web applications and a set of reusable PHP components. Symfony is used by thousands of web applications (including BlaBlaCar.com and Spotify.com) and most of the popular PHP projects (including Drupal and Magento).

Installation

Documentation

Community

Contributing

Symfony is an Open Source, community-driven project with thousands of contributors. Join them contributing code or contributing documentation.

Security Issues

If you discover a security vulnerability within Symfony, please follow our disclosure procedure.

About Us

Symfony development is sponsored by SensioLabs, led by the Symfony Core Team and supported by Symfony contributors.