Parameters

A parameter is a named value stored in the container, written once and referred to as %name% from any configuration file.

Syntax%parameter.name% / #[Autowire(param: 'parameter.name')]

A parameter is a named value stored in the container alongside your services. It exists so a value can be written in one place and referred to from any configuration file, and so that a value a person might change is not buried inside a class.

Defining and referring

Parameters go under the parameters key of config/services.yaml. Anywhere in configuration, %name% means the value of the parameter called name, and one parameter may refer to another. Symfony defines some itself, including kernel.project_dir, kernel.environment, kernel.debug, kernel.cache_dir and kernel.logs_dir. A literal percent sign has to be doubled, so 100%% is the string 100%.

Getting one into a class

The short form is the #[Autowire] attribute with the param: option on a constructor argument. The long forms do the same thing: bind the argument by name under services._defaults.bind, or inject ContainerBagInterface and call get(). Prefer the attribute, because it states the single value the class needs instead of handing it every parameter in the application.

Parameter or constant

A PHP constant is fine when the value never varies and only PHP reads it. Use a parameter when another package's configuration must see the value, or when it differs between environments. Parameters are resolved when the container is compiled and then frozen into it, so a parameter cannot change while the application runs. Values that must change at runtime belong in environment variables.

Example

Example · php
// src/Service/InvoiceNumberFormatter.php
declare(strict_types=1);

namespace App\Service;

use Symfony\Component\DependencyInjection\Attribute\Autowire;

final class InvoiceNumberFormatter
{
    public function __construct(
        // app.invoice_prefix is defined under "parameters" in config/services.yaml
        #[Autowire(param: 'app.invoice_prefix')]
        private string $prefix,
    ) {
    }

    public function format(int $number, int $year): string
    {
        // %05d pads the counter to five digits; %% would be needed for a literal %
        return sprintf('%s-%d-%05d', $this->prefix, $year, $number);
    }
}

// $formatter = new InvoiceNumberFormatter('SC');
// echo $formatter->format(42, 2026);
// Output: SC-2026-00042

When to use it

  • Keep an invoice or reference prefix out of the class that formats it.
  • Share one directory path between your services and a package's configuration.
  • Give a value a name so a reviewer can see what is configurable without reading the class.

More examples

Defining the parameters

Shows both halves of the pair. The attribute in the primary example and this bind block do the same job; bind is useful when the same argument name appears in several classes, so you set it once rather than annotating each constructor.

Example · yaml
# config/services.yaml
parameters:
    app.invoice_prefix: 'SC'
    app.supported_locales: ['en', 'es', 'fr']
    # one parameter may refer to another
    app.reports_dir: '%kernel.project_dir%/var/reports'
    # %% is a literal percent sign
    app.discount_label: '10%% off'

services:
    _defaults:
        autowire: true
        autoconfigure: true
        # the long form of #[Autowire(param: ...)]: bind by argument name
        bind:
            $reportsDir: '%app.reports_dir%'

Reading parameters through the bag

The longhand. It is the right tool when a class genuinely needs several parameters chosen at runtime, for example a lookup by key. For one or two known values the attribute is clearer, because the constructor signature then tells you what the class depends on.

Example · php
// src/Service/ReportArchive.php
declare(strict_types=1);

namespace App\Service;

use Symfony\Component\DependencyInjection\ParameterBag\ContainerBagInterface;

final class ReportArchive
{
    public function __construct(
        private ContainerBagInterface $params,
    ) {
    }

    public function pathFor(string $file): string
    {
        // get() throws if the parameter does not exist
        return $this->params->get('app.reports_dir').'/'.$file;
    }
}

// With app.reports_dir = /srv/app/var/reports:
// echo (new ReportArchive($params))->pathFor('q1.csv');
// Output: /srv/app/var/reports/q1.csv

Listing what is defined

Useful when a %placeholder% fails to resolve and you need to know the exact name, or when you inherit a project and want to see which values the previous author made configurable.

Example · bash
# every parameter in the compiled container, including Symfony's own
$ php bin/console debug:container --parameters

# filter by name
$ php bin/console debug:container --parameters | grep app.

Discussion

  • Be the first to comment on this lesson.