Symfony
sponsored by SensioLabs
Menu
  • About
  • Documentation
  • Screencasts
  • Cloud
  • Certification
  • Community
  • Businesses
  • News
  • Download
  1. Home
  2. Documentation
  3. Components
  4. The OptionsResolver Component
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud
Search by Algolia

Table of Contents

  • Installation
  • Usage
  • Configuring the OptionsResolver
    • Required Options
    • Optional Options
    • Set Default Values
    • Default Values that depend on another Option
    • Configure allowed Values
    • Configure allowed Types
    • Normalize the Options

The OptionsResolver Component

Edit this page

Warning: You are browsing the documentation for Symfony 2.1, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

The OptionsResolver Component

The OptionsResolver Component helps you configure objects with option arrays. It supports default values, option constraints and lazy options.

Installation

You can install the component in 2 different ways:

  • Use the official Git repository (https://github.com/symfony/OptionsResolver
  • Install it via Composer (symfony/options-resolver on Packagist)

Usage

Imagine you have a Mailer class which has 2 options: host and password. These options are going to be handled by the OptionsResolver Component.

First, create the Mailer class:

1
2
3
4
5
6
7
8
class Mailer
{
    protected $options;

    public function __construct(array $options = array())
    {
    }
}

You could of course set the $options value directly on the property. Instead, use the OptionsResolver class and let it resolve the options by calling resolve(). The advantages of doing this will become more obvious as you continue:

1
2
3
4
5
6
7
8
9
use Symfony\Component\OptionsResolver\OptionsResolver;

// ...
public function __construct(array $options = array())
{
    $resolver = new OptionsResolver();

    $this->options = $resolver->resolve($options);
}

The $options property is an instance of Options, which implements ArrayAccess, Iterator and Countable. That means you can handle it just like a normal array:

1
2
3
4
5
6
7
8
9
10
// ...
public function getHost()
{
    return $this->options['host'];
}

public function getPassword()
{
    return $this->options['password'];
}

Configuring the OptionsResolver

Now, try to actually use the class:

1
2
3
4
5
6
$mailer = new Mailer(array(
    'host'     => 'smtp.example.org',
    'password' => 'pa$$word',
));

echo $mailer->getPassword();

Right now, you'll receive a
InvalidOptionsException, which tells you that the options host and password do not exist. This is because you need to configure the OptionsResolver first, so it knows which options should be resolved.

Tip

To check if an option exists, you can use the isKnown() function.

A best practice is to put the configuration in a method (e.g. setDefaultOptions). You call this method in the constructor to configure the OptionsResolver class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class Mailer
{
    protected $options;

    public function __construct(array $options = array())
    {
        $resolver = new OptionsResolver();
        $this->setDefaultOptions($resolver);

        $this->options = $resolver->resolve($options);
    }

    protected function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        // ... configure the resolver, you will learn this in the sections below
    }
}

Required Options

The host option is required: the class can't work without it. You can set the required options by calling setRequired():

1
2
3
4
5
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setRequired(array('host'));
}

You are now able to use the class without errors:

1
2
3
4
5
$mailer = new Mailer(array(
    'host' => 'smtp.example.org',
));

echo $mailer->getHost(); // 'smtp.example.org'

If you don't pass a required option, a MissingOptionsException will be thrown.

To determine if an option is required, you can use the isRequired() method.

Optional Options

Sometimes, an option can be optional (e.g. the password option in the Mailer class). You can configure these options by calling setOptional():

1
2
3
4
5
6
7
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setOptional(array('password'));
}

Set Default Values

Most of the optional options have a default value. You can configure these options by calling setDefaults():

1
2
3
4
5
6
7
8
9
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setDefaults(array(
        'username' => 'root',
    ));
}

This would add a third option - username - and give it a default value of root. If the user passes in a username option, that value will override this default. You don't need to configure username as an optional option. The OptionsResolver already knows that options with a default value are optional.

The OptionsResolver component also has an replaceDefaults() method. This can be used to override the previous default value. The closure that is passed has 2 parameters:

  • $options (an Options instance), with all the default options
  • $value, the previous set default value

Default Values that depend on another Option

Suppose you add a port option to the Mailer class, whose default value you guess based on the host. You can do that easily by using a Closure as the default value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setDefaults(array(
        'port' => function (Options $options) {
            if (in_array($options['host'], array('127.0.0.1', 'localhost'))) {
                return 80;
            }
            
            return 25;
        },
    ));
}

Caution

The first argument of the Closure must be typehinted as Options, otherwise it is considered as the value.

Configure allowed Values

Not all values are valid values for options. Suppose the Mailer class has a transport option, it can only be one of sendmail, mail or smtp. You can configure these allowed values by calling setAllowedValues():

1
2
3
4
5
6
7
8
9
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setAllowedValues(array(
        'transport' => array('sendmail', 'mail', 'smtp'),
    ));
}

There is also an addAllowedValues() method, which you can use if you want to add an allowed value to the previously set allowed values.

Configure allowed Types

You can also specify allowed types. For instance, the port option can be anything, but it must be an integer. You can configure these types by calling setAllowedTypes():

1
2
3
4
5
6
7
8
9
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setAllowedTypes(array(
        'port' => 'integer',
    ));
}

Possible types are the ones associated with the is_* php functions or a class name. You can also pass an array of types as the value. For instance, array('null', 'string') allows port to be null or a string.

There is also an addAllowedTypes() method, which you can use to add an allowed type to the previous allowed types.

Normalize the Options

Some values need to be normalized before you can use them. For instance, pretend that the host should always start with http://. To do that, you can write normalizers. These Closures will be executed after all options are passed and should return the normalized value. You can configure these normalizers by calling setNormalizers():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setNormalizers(array(
        'host' => function (Options $options, $value) {
            if ('http://' !== substr($value, 0, 7)) {
                $value = 'http://'.$value;
            }

            return $value;
        },
    ));
}

You see that the closure also gets an $options parameter. Sometimes, you need to use the other options for normalizing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ...
protected function setDefaultOptions(OptionsResolverInterface $resolver)
{
    // ...

    $resolver->setNormalizers(array(
        'host' => function (Options $options, $value) {
            if (!in_array(substr($value, 0, 7), array('http://', 'https://'))) {
                if ($options['ssl']) {
                    $value = 'https://'.$value;
                } else {
                    $value = 'http://'.$value;
                }
            }

            return $value;
        },
    ));
}
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
We stand with Ukraine.
Version:
Become certified from home

Become certified from home

Check Code Performance in Dev, Test, Staging & Production

Check Code Performance in Dev, Test, Staging & Production

↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

Avatar of Gary Houbre, a Symfony contributor

Thanks Gary Houbre (@thegarious) for being a Symfony contributor

29 commits • 357 lines changed

View all contributors that help us make Symfony

Become a Symfony contributor

Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

Learn how to contribute

Symfony™ is a trademark of Symfony SAS. All rights reserved.

  • What is Symfony?
    • Symfony at a Glance
    • Symfony Components
    • Case Studies
    • Symfony Releases
    • Security Policy
    • Logo & Screenshots
    • Trademark & Licenses
    • symfony1 Legacy
  • Learn Symfony
    • Symfony Docs
    • Symfony Book
    • Reference
    • Bundles
    • Best Practices
    • Training
    • eLearning Platform
    • Certification
  • Screencasts
    • Learn Symfony
    • Learn PHP
    • Learn JavaScript
    • Learn Drupal
    • Learn RESTful APIs
  • Community
    • SymfonyConnect
    • Support
    • How to be Involved
    • Code of Conduct
    • Events & Meetups
    • Projects using Symfony
    • Downloads Stats
    • Contributors
    • Backers
  • Blog
    • Events & Meetups
    • A week of symfony
    • Case studies
    • Cloud
    • Community
    • Conferences
    • Diversity
    • Documentation
    • Living on the edge
    • Releases
    • Security Advisories
    • SymfonyInsight
    • Twig
    • SensioLabs
  • Services
    • SensioLabs services
    • Train developers
    • Manage your project quality
    • Improve your project performance
    • Host Symfony projects
    Deployed on
Follow Symfony
Search by Algolia