Buy Access to Course
04.

Making all Services Private

Share this awesome video!

|

There is one more key that lives under _defaults in a new Symfony 3.3 project: public: false:

42 lines | app/config/services.yml
// ... lines 1 - 8
services:
_defaults:
// ... lines 11 - 12
public: false
// ... lines 14 - 42

The idea of public versus private services is not new in Symfony 3.3... but defaulting all services to private is new, and it's a critical change. Thanks to this, every service in this file is now private. What does that mean? One simple thing: when a service is private, you cannot fetch it directly from the container via $container->get(). So, for example, $container->get('AppBundle\Service\MarkdownTransformer') will not work.

Tip

In Symfony 3.3, sometimes you can fetch a private service directly from the container. But doing this has been deprecated and will be removed in Symfony 4.

But, everything else works the same: I can pass this service as an argument and it can be autowired into an argument. Only the $container->get() usage changed.

In our app, making this change is safe! We just created all of these service ids a minute ago and they're not being used anywhere yet, definitely not with $container->get(). The exception is the last two services: we might be fetching these services directly from the container. And in fact, I know we are: in src/AppBundle/Controller/Admin/GenusAdminController.php. Down in editAction(), we're fetching both services via $this->get(), which is a shortcut for $this->container->get():

// ... lines 1 - 15
class GenusAdminController extends Controller
{
// ... lines 18 - 63
public function editAction(Request $request, Genus $genus)
{
// ... lines 66 - 69
if ($form->isSubmitted() && $form->isValid()) {
// ... lines 71 - 76
$this->addFlash(
'success',
$this->get('app.encouraging_message_generator')->getMessage()
);
// ... lines 81 - 84
} elseif ($form->isSubmitted()) {
$this->addFlash(
'error',
$this->get('app.discouraging_message_generator')->getMessage()
);
}
// ... lines 91 - 94
}
}

That means, for now, to keep our app working, add public: true under each service:

42 lines | app/config/services.yml
// ... lines 1 - 8
services:
// ... lines 10 - 30
app.encouraging_message_generator:
// ... lines 32 - 34
public: true
// ... line 36
app.discouraging_message_generator:
// ... lines 38 - 40
public: true

Aliases can also be private... but in legacy_aliases.yml, there is no _defaults key with public: false. So, these are all public aliases... which is exactly what we want, ya know, because we're trying not to break our app!

Like with every step so far, our app should still work fine. Woohoo! But... you may be wondering why we made the services private. Doesn't this just make our services harder to use? As we'll learn soon, when you use private services, it becomes impossible to make a mistake and accidentally reference a non-existent service. Private services are going to make our app even more dependable than before. And also, a little bit faster.

Next, let's talk about the biggest change to this file: auto-registration of all classes in src/AppBundle as services. Woh.