Parameters
A parameter is a named value stored in the container, written once and referred to as %name% from any configuration file.
%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
// 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.
# 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.
// 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.csvListing 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.
# 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