How to get parameter in Symfony controller

How to get parameter in Symfony controller banner

To get parameters in Symfony controller, you can bind a parameter to a variable and inject it into a controller or service.

There are several ways to get parameters in Symfony controller, and the recommended one is to use bind parameters. 

Let's see how that works.

Get parameter in controller by using bind

# config/services.yaml
services:
    _defaults:
        bind:
            $adminEmail: '[email protected]'
            $projectDir: '%kernel.project_dir%'

Now, these two parameters are available in any service constructor, including controllers and controller arguments.

// ..
class HomeController extends AbstractController
{
    public function __construct($adminEmail, $projectDir) {
      // $adminEmail
      // $projectDir
    }

    #[Route('/', name: 'home')]
    public function index(Request $request, $adminEmail, $projectDir) {
      // $adminEmail
      // $projectDir
    }

Pretty neat, right?

How to get parameters in a service?

No problem. Binded parameters are available in services as well.

// src/Service/MyService.php
class MyService
{
    public function __construct($adminEmail, $projectDir) {
      // $adminEmail
      // $projectDir
    }
// ..

What if my service needs a lot of parameters?

Binding and injecting a lot of parameters can be cumbersome. For that particular use case, you can use ParameterBagInterface and retrieve parameters from it.

Let's see how that works.

 // src/Service/GreedyService.php

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class GreedyService
{
    public function __construct(ParameterBagInterface $params) {
      $params->get('admin_email');
      $params->get('%kernel.project_dir%');
      // ..
    }
// ..
 

and your config/services.yaml should have parameters defined:

# config/services.yaml
parameters:
    admin_email: '[email protected]'

ParameterBagInterface should be used as a last resort only if a lot of parameters are needed in a single service.

Note that in such cases, you can try to split your service into smaller services.

In general, if a service has a lot of dependencies, that could mean it has many responsibilities, and managing that can be hard and cumbersome.

How to get an env variable in controller or a service?

You can bind env variables as well.

# config/services.yaml
services:
    _defaults:
        bind:
            $adminEmail: '%env(string:ADMIN_EMAIL)%'

Conclusion

In a Symfony project, the Law of Demeter remains an important principle to consider when injecting parameters into classes. This principle encourages minimizing the knowledge and dependencies between objects.

When dealing with parameter injection, especially in the context of Symfony's dependency injection system, you should strive to keep the injected parameters as relevant and specific as possible rather than providing access to a wide range of parameters through the ParameterBagInterface.