Skip to content

Commit

Permalink
Improve/fix container doc
Browse files Browse the repository at this point in the history
  • Loading branch information
noniagriconomie committed Oct 15, 2020
1 parent 295e7da commit 31617f9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 32 deletions.
70 changes: 39 additions & 31 deletions service_container.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ service's class or interface name. Want to :doc:`log </logging>` something? No p
namespace App\Controller;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;

class ProductController
{
/**
* @Route("/products")
*/
public function list(LoggerInterface $logger)
public function list(LoggerInterface $logger): Response
{
$logger->info('Look! I just used a service');
$logger->info('Look, I just used a service!');

// ...
}
Expand Down Expand Up @@ -101,7 +102,7 @@ it can't be re-used. Instead, you decide to create a new class::

class MessageGenerator
{
public function getHappyMessage()
public function getHappyMessage(): string
{
$messages = [
'You did it! You updated the system! Amazing!',
Expand All @@ -118,9 +119,14 @@ it can't be re-used. Instead, you decide to create a new class::
Congratulations! You've created your first service class! You can use it immediately
inside your controller::

// src/Controller/ProductController.php
use App\Service\MessageGenerator;
use Symfony\Component\HttpFoundation\Response;

public function new(MessageGenerator $messageGenerator)
/**
* @Route("/products/new")
*/
public function new(MessageGenerator $messageGenerator): Response
{
// thanks to the type-hint, the container will instantiate a
// new MessageGenerator and pass it to you!
Expand Down Expand Up @@ -241,7 +247,7 @@ and use it later::
$this->logger = $logger;
}

public function getHappyMessage()
public function getHappyMessage(): string
{
$this->logger->info('About to find a happy message!');
// ...
Expand Down Expand Up @@ -291,8 +297,8 @@ Handling Multiple Services
Suppose you also want to email a site administrator each time a site update is
made. To do that, you create a new class::

// src/Updates/SiteUpdateManager.php
namespace App\Updates;
// src/Service/SiteUpdateManager.php
namespace App\Service;

use App\Service\MessageGenerator;
use Symfony\Component\Mailer\MailerInterface;
Expand All @@ -309,7 +315,7 @@ made. To do that, you create a new class::
$this->mailer = $mailer;
}

public function notifyOfSiteUpdate()
public function notifyOfSiteUpdate(): bool
{
$happyMessage = $this->messageGenerator->getHappyMessage();

Expand All @@ -322,6 +328,8 @@ made. To do that, you create a new class::
$this->mailer->send($email);

// ...

return true;
}
}

Expand All @@ -334,7 +342,7 @@ you can type-hint the new ``SiteUpdateManager`` class and use it::
namespace App\Controller;
// ...
use App\Updates\SiteUpdateManager;
use App\Service\SiteUpdateManager;

public function new(SiteUpdateManager $siteUpdateManager)
{
Expand All @@ -361,29 +369,29 @@ example, suppose you want to make the admin email configurable:

.. code-block:: diff
// src/Updates/SiteUpdateManager.php
// src/Service/SiteUpdateManager.php
// ...
class SiteUpdateManager
{
// ...
+ private $adminEmail;
- public function __construct(MessageGenerator $messageGenerator, \Swift_Mailer $mailer)
+ public function __construct(MessageGenerator $messageGenerator, \Swift_Mailer $mailer, $adminEmail)
- public function __construct(MessageGenerator $messageGenerator, MailerInterface $mailer)
+ public function __construct(MessageGenerator $messageGenerator, MailerInterface $mailer, $adminEmail)
{
// ...
+ $this->adminEmail = $adminEmail;
}
public function notifyOfSiteUpdate()
public function notifyOfSiteUpdate(): bool
{
// ...
$message = \Swift_Message::newInstance()
$email = (new Email())
// ...
- ->setTo('[email protected]')
+ ->setTo($this->adminEmail)
- ->to('[email protected]')
+ ->to($this->adminEmail)
// ...
;
// ...
Expand All @@ -392,7 +400,7 @@ example, suppose you want to make the admin email configurable:
If you make this change and refresh, you'll see an error:

Cannot autowire service "App\Updates\SiteUpdateManager": argument "$adminEmail"
Cannot autowire service "App\Service\SiteUpdateManager": argument "$adminEmail"
of method "__construct()" must have a type-hint or be given a value explicitly.

That makes sense! There is no way that the container knows what value you want to
Expand All @@ -412,7 +420,7 @@ pass here. No problem! In your configuration, you can explicitly set this argume
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# explicitly configure the service
App\Updates\SiteUpdateManager:
App\Service\SiteUpdateManager:
arguments:
$adminEmail: '[email protected]'
Expand All @@ -436,7 +444,7 @@ pass here. No problem! In your configuration, you can explicitly set this argume
/>
<!-- Explicitly configure the service -->
<service id="App\Updates\SiteUpdateManager">
<service id="App\Service\SiteUpdateManager">
<argument key="$adminEmail">[email protected]</argument>
</service>
</services>
Expand All @@ -447,7 +455,7 @@ pass here. No problem! In your configuration, you can explicitly set this argume
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Updates\SiteUpdateManager;
use App\Service\SiteUpdateManager;
return function(ContainerConfigurator $configurator) {
// ...
Expand Down Expand Up @@ -877,7 +885,7 @@ But, if you *do* need to make a service public, override the ``public`` setting:
# ... same code as before
# explicitly configure the service
Acme\PublicService:
App\Service\PublicService:
public: true
.. code-block:: xml
Expand All @@ -893,7 +901,7 @@ But, if you *do* need to make a service public, override the ``public`` setting:
<!-- ... same code as before -->
<!-- Explicitly configure the service -->
<service id="Acme\PublicService" public="true"></service>
<service id="App\Service\PublicService" public="true"></service>
</services>
</container>
Expand All @@ -902,13 +910,13 @@ But, if you *do* need to make a service public, override the ``public`` setting:
// config/services.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use Acme\PublicService;
use App\Service\PublicService;
return function(ContainerConfigurator $configurator) {
// ... same as code before
// explicitly configure the service
$services->set(PublicService::class)
$services->set(Service\PublicService::class)
->public()
;
};
Expand Down Expand Up @@ -1087,7 +1095,7 @@ admin email. In this case, each needs to have a unique service id:
# this is the service's id
site_update_manager.superadmin:
class: App\Updates\SiteUpdateManager
class: App\Service\SiteUpdateManager
# you CAN still use autowiring: we just want to show what it looks like without
autowire: false
# manually wire all arguments
Expand All @@ -1097,7 +1105,7 @@ admin email. In this case, each needs to have a unique service id:
- '[email protected]'
site_update_manager.normal_users:
class: App\Updates\SiteUpdateManager
class: App\Service\SiteUpdateManager
autowire: false
arguments:
- '@App\Service\MessageGenerator'
Expand All @@ -1106,7 +1114,7 @@ admin email. In this case, each needs to have a unique service id:
# Create an alias, so that - by default - if you type-hint SiteUpdateManager,
# the site_update_manager.superadmin will be used
App\Updates\SiteUpdateManager: '@site_update_manager.superadmin'
App\Service\SiteUpdateManager: '@site_update_manager.superadmin'
.. code-block:: xml
Expand All @@ -1120,19 +1128,19 @@ admin email. In this case, each needs to have a unique service id:
<services>
<!-- ... -->
<service id="site_update_manager.superadmin" class="App\Updates\SiteUpdateManager" autowire="false">
<service id="site_update_manager.superadmin" class="App\Service\SiteUpdateManager" autowire="false">
<argument type="service" id="App\Service\MessageGenerator"/>
<argument type="service" id="mailer"/>
<argument>[email protected]</argument>
</service>
<service id="site_update_manager.normal_users" class="App\Updates\SiteUpdateManager" autowire="false">
<service id="site_update_manager.normal_users" class="App\Service\SiteUpdateManager" autowire="false">
<argument type="service" id="App\Service\MessageGenerator"/>
<argument type="service" id="mailer"/>
<argument>[email protected]</argument>
</service>
<service id="App\Updates\SiteUpdateManager" alias="site_update_manager.superadmin"/>
<service id="App\Service\SiteUpdateManager" alias="site_update_manager.superadmin"/>
</services>
</container>
Expand All @@ -1142,7 +1150,7 @@ admin email. In this case, each needs to have a unique service id:
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Service\MessageGenerator;
use App\Updates\SiteUpdateManager;
use App\Service\SiteUpdateManager;
return function(ContainerConfigurator $configurator) {
// ...
Expand Down
2 changes: 1 addition & 1 deletion testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ it via that alias:
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\Service\MessageGenerator;
use App\Updates\SiteUpdateManager;
use App\Service\SiteUpdateManager;
return function(ContainerConfigurator $configurator) {
// ...
Expand Down

0 comments on commit 31617f9

Please sign in to comment.