- Complete Working Example
- Symfony - CMF Edition
- Symfony - REST Edition
- Symfony - Advanced Concepts
- Symfony - Unit Testing
- Symfony - Email Management
- Symfony - Logging
- Symfony - Internationalization
- Cookies & Session Management
- Symfony - Ajax Control
- Symfony - File Uploading
- Symfony - Validation
- Symfony - Forms
- Symfony - Doctrine ORM
- Symfony - View Engine
- Symfony - Routing
- Symfony - Controllers
- Creating a Simple Web Application
- Symfony - Bundles
- Symfony - Expression
- Symfony - Events & EventListener
- Symfony - Service Container
- Symfony - Components
- Symfony - Architecture
- Symfony - Installation
- Symfony - Introduction
- Symfony - Home
Symfony Useful Resources
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Symfony - Service Container
In any apppcation, objects tend to increase as the apppcation grows. As objects increase, the dependency between the objects also increases. Object dependency needs to be handled properly for a successful apppcation.
As discussed in the Components chapter, Symfony provides an easy and efficient component, DependencyInjection to handle object dependency. A service container is a container of objects with properly resolved dependency between them. Let us learn how to use DependencyInjection component in this chapter.
Let us create a Greeter class. The purpose of the Greeter class is to greet the user as shown in the following example.
$greeter = new Greeter( Hi ); $greeter->greet( Jon ); // print "Hi, Jon"
The complete code of the Greeter class is as follows.
class Greeter { private $greetingText; pubpc function __construct($greetingText) { $this->greetingText = $greetingText; } pubpc function greet($name) { echo $this->greetingText . ", " . $name . " "; } }
Now, let us add Greeter class to the service container. Symfony provides ContainerBuilder to create a new container. Once the container is created, Greeter class can be registered into it using the container s register method.
use SymfonyComponentDependencyInjectionContainerBuilder; $container = new ContainerBuilder(); $container ->register( greeter , Greeter ) ->addArgument( Hi );
Here, we have used static argument to specify the greeting text, Hi. Symfony provides a dynamic setting of parameter as well. To use a dynamic parameter, we need to choose a name and specify it between % and the parameter can be set using container s setParameter method.
$container = new ContainerBuilder(); $container ->register( greeter , Greeter ) ->addArgument( %greeter.text% ); $container->setParameter( greeter.text , Hi );
We have registered a Greeter class with proper setting. Now, we can ask the container to provide a properly configured Greeter object using the container get method.
$greeter = $container->get( greeter ); $greeter->greet( Jon ); // prints "Hi, Jon"
We have successfully registered a class, Greeter into container, fetched it from the container and used it. Now, let us create another class User, which use Greeter class and see how to register it.
class User { private $greeter; pubpc $name; pubpc $age; pubpc function setGreeter(Greeter $greeter) { $this->greeter = $greeter; } pubpc function greet() { $this->greeter->greet($this->name); } }
The User class gets the Greeter class using one of its setter method, setGreeter. For this scenario, Symfony provides a method, addMethodCall and a class, Reference to refer another class as shown in the following code.
use SymfonyComponentDependencyInjectionReference; $container ->register( user , User ) ->addMethodCall( setGreeter , array(new Reference( greeter )));
Finally, we have registered two classes, Greeter and User having a strong relation between them. Now, we can safely fetch the User object with properly configured Greeter class from the container as shown in the following code.
$container->setParameter( greeter.text , Hi ); $user = $container->get( user ); $user->name = "Jon"; $user->age = 20; $user->greet(); // Prints "Hi, Jon"
We have seen how to configure an object in a container using PHP itself. Symfony provides other mechanisms as well. They are XML and YAML configuration files. Let us see how to configure a container using YAML. For this, install symfony/config and symfony/yaml components along with symfony/dependency-injection components.
cd /path/to/dir mkdir dependency-injection-example cd dependency-injection-example composer require symfony/dependency-injection composer require symfony/config composer require symfony/yaml
YAML configuration will be written in a separate file, services.yml. YAML configuration consists of two sections, parameters and services. Parameters section defines all required parameters. Services section defines all objects. Services section is further spanided into multiple sections namely, class, arguments, and calls. Class specifies the actual class. Arguments specifies the constructor s arguments. Finally, calls specify the setter methods. Another class can be referred using @ symbol, @greeter.
parameters: greeter.text: Hello services: greeter: class: Greeter arguments: [ %greeter.text% ] user: class: User calls: - [setGreeter, [ @greeter ]]
Now, services.yml can be loaded and configured using FileLoader and YamlFileLoader as shown in the following code.
use SymfonyComponentConfigFileLocator; use SymfonyComponentDependencyInjectionLoaderYamlFileLoader; $yamlContainer = new ContainerBuilder(); $loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__)); $loader->load( services.yml ); $yamlUser = $yamlContainer->get( user ); $yamlUser->name = "Jon"; $yamlUser->age = 25; $yamlUser->greet();
The complete code psting is as follows.
main.php
<?php require __DIR__ . /vendor/autoload.php ; use SymfonyComponentDependencyInjectionContainerBuilder; use SymfonyComponentConfigFileLocator; use SymfonyComponentDependencyInjectionLoaderYamlFileLoader; use SymfonyComponentDependencyInjectionReference; class Greeter { private $greetingText; pubpc function __construct($greetingText) { $this->greetingText = $greetingText; } pubpc function greet($name) { echo $this->greetingText . ", " . $name . " "; } } class User { private $greeter; pubpc $name; pubpc $age; pubpc function setGreeter(Greeter $greeter) { $this->greeter = $greeter; } pubpc function greet() { $this->greeter->greet($this->name); } } $container = new ContainerBuilder(); $container ->register( greeter , Greeter ) ->addArgument( %greeter.text% ); $container ->register( user , User ) ->addMethodCall( setGreeter , array(new Reference( greeter ))); $container->setParameter( greeter.text , Hi ); $greeter = $container->get( greeter ); $greeter->greet( Jon ); $user = $container->get( user ); $user->name = "Jon"; $user->age = 20; $user->greet(); $yamlContainer = new ContainerBuilder(); $loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__)); $loader->load( services.yml ); $yamlHello = $yamlContainer->get( greeter ); $yamlHello->greet( Jon ); $yamlUser = $yamlContainer->get( user ); $yamlUser->name = "Jon"; $yamlUser->age = 25; $yamlUser->greet(); ?>
services.yml
parameters: greeter.text: Hello services: greeter: class: Greeter arguments: [ %greeter.text% ] user: class: User calls: - [setGreeter, [ @greeter ]]
Symfony web framework uses the dependency injection component extensively. All the components are bound by the centrapzed service container. Symfony web framework exposes the container in all its Controller through container property. We can get all object registered in it, say logger, mailer, etc., through it.
$logger = $this->container->get( logger ); $logger->info( Hi );
To find the object registered in the container, use the following command.
cd /path/to/app php bin/console debug:container
There are around 200+ objects in the hello web app created in the installation chapter.
Advertisements