WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.066 --> 00:00:02.756 align:middle
Let's talk about services.

00:00:03.056 --> 00:00:05.466 align:middle
These are the most important concept in Symfony.

00:00:05.856 --> 00:00:10.196 align:middle
And once you understand them,
honestly, you'll be able to do anything.

00:00:10.886 --> 00:00:13.906 align:middle
First, a service is an object that does work.

00:00:14.256 --> 00:00:14.776 align:middle
That's it.

00:00:15.236 --> 00:00:20.496 align:middle
For example, if you instantiated a Logger object
that has a log() method, that's a service!

00:00:20.756 --> 00:00:23.066 align:middle
It does work: it logs things!

00:00:23.466 --> 00:00:28.296 align:middle
Or if you created a database connection object
that makes queries to the database then...

00:00:28.556 --> 00:00:30.396 align:middle
yup! That's a service too.

00:00:31.076 --> 00:00:31.466 align:middle
So then...

00:00:31.586 --> 00:00:34.276 align:middle
if a service is just an object that does work...

00:00:34.476 --> 00:00:37.046 align:middle
what lazy objects aren't services?

00:00:37.616 --> 00:00:41.636 align:middle
Our Starship class is a perfect
example of a non service.

00:00:42.046 --> 00:00:45.816 align:middle
It's main job is not to do
work: it's to hold data.

00:00:46.396 --> 00:00:48.806 align:middle
Sure, it has a few public methods...

00:00:48.806 --> 00:00:52.656 align:middle
and you could even put some logic
inside of these methods to do something.

00:00:53.136 --> 00:00:56.966 align:middle
But ultimately, it's not a
worker, it's a data holder.

00:00:57.506 --> 00:00:58.986 align:middle
What about controller classes?

00:00:59.396 --> 00:01:01.046 align:middle
Yeah, they're services too.

00:01:01.376 --> 00:01:03.776 align:middle
Their work is to create response objects.

00:01:04.406 --> 00:01:09.256 align:middle
Anyway, every bit of work that's done in
Symfony is actually done by a service.

00:01:09.656 --> 00:01:11.416 align:middle
Writing log messages to this file?

00:01:11.836 --> 00:01:13.246 align:middle
Yeah, there's a service for that.

00:01:13.786 --> 00:01:16.486 align:middle
Figuring out which route
matches the current URL?

00:01:16.756 --> 00:01:18.206 align:middle
That's the router service!

00:01:18.766 --> 00:01:20.576 align:middle
What about rendering a twig template?

00:01:21.056 --> 00:01:24.336 align:middle
Yep, it turns out that the
render() method is a shortcut

00:01:24.336 --> 00:01:27.826 align:middle
to find the correct service
object and call a method on it.

00:01:28.566 --> 00:01:31.866 align:middle
You may sometimes also hear that
these services are organized

00:01:31.866 --> 00:01:34.806 align:middle
into a big object called
the "service container".

00:01:34.806 --> 00:01:38.186 align:middle
You can think of the container
like a giant associative array

00:01:38.186 --> 00:01:41.396 align:middle
of service objects, each with a unique id.

00:01:41.986 --> 00:01:44.616 align:middle
Want to see a list of every
service in our app right now?

00:01:45.026 --> 00:01:52.666 align:middle
Me too! Find your terminal and run: bin/console
debug:container That's a lot of services!

00:01:53.176 --> 00:01:56.266 align:middle
Let me make this smaller so
each fits on its own line...

00:01:56.826 --> 00:02:00.396 align:middle
better. On the left side, we
see the ID of each service.

00:02:00.726 --> 00:02:04.866 align:middle
And on the right, the class of the
object that the ID corresponds to.

00:02:05.396 --> 00:02:05.976 align:middle
Cool, right?

00:02:06.866 --> 00:02:11.826 align:middle
Go back to our controller and hold control or
command to open up the json() method again.

00:02:12.386 --> 00:02:14.366 align:middle
Now this makes more sense!

00:02:14.896 --> 00:02:20.026 align:middle
It's checking to see if the container
has a service whose ID is serializer.

00:02:20.656 --> 00:02:23.656 align:middle
If it does, it grabs that
service from the container

00:02:23.796 --> 00:02:25.626 align:middle
and calls the serialize() method on it.

00:02:26.406 --> 00:02:30.086 align:middle
When we work with services, it
won't look exactly like this.

00:02:30.436 --> 00:02:34.026 align:middle
But the super important thing is that
we now understand what's going on.

00:02:34.656 --> 00:02:37.586 align:middle
My next question is: where
do these services come from?

00:02:37.956 --> 00:02:41.196 align:middle
Like, who says there's a
service whose ID is twig...

00:02:41.536 --> 00:02:47.026 align:middle
and that when we ask the container for it,
it should return a twig Environment object?

00:02:47.586 --> 00:02:50.716 align:middle
The answer is: entirely from bundles.

00:02:51.066 --> 00:02:53.916 align:middle
In fact, that's the main point
of installing a new bundle.

00:02:54.236 --> 00:02:55.966 align:middle
Bundles give us services.

00:02:56.686 --> 00:02:58.026 align:middle
Remember when we installed twig?

00:02:58.486 --> 00:03:00.306 align:middle
It added a bundle to our app.

00:03:00.696 --> 00:03:01.926 align:middle
And guess what that bundle did?

00:03:02.336 --> 00:03:06.436 align:middle
Yup: it gave us new services,
including the twig service.

00:03:07.126 --> 00:03:08.486 align:middle
Bundles give us services...

00:03:08.606 --> 00:03:10.446 align:middle
and services are tools.

00:03:10.926 --> 00:03:13.526 align:middle
And though there are many services in this list,

00:03:13.746 --> 00:03:19.576 align:middle
the vast majority of these are low-level service
objects that we won't ever use or care about.

00:03:20.316 --> 00:03:23.496 align:middle
We also won't care about the ID
of the services most of the time.

00:03:24.256 --> 00:03:26.666 align:middle
Instead, run a related command called:

00:03:26.666 --> 00:03:33.096 align:middle
php bin/console debug:autowiring This shows
us all the services that are autowireable,

00:03:33.326 --> 00:03:36.736 align:middle
which is the technique that
we'll use to fetch services.

00:03:37.226 --> 00:03:41.796 align:middle
It's basically a curated list of the
services that we're most likely to need.

00:03:42.646 --> 00:03:46.496 align:middle
So let's do a challenge: let's
log something from our controller.

00:03:47.046 --> 00:03:49.326 align:middle
Here's a sneak peek into
how I approach this problem

00:03:49.326 --> 00:03:52.196 align:middle
in my brain: Ok, I need to log something!

00:03:52.526 --> 00:03:54.126 align:middle
And... logging is work.

00:03:54.456 --> 00:03:56.226 align:middle
And... services do work!

00:03:56.586 --> 00:03:59.736 align:middle
Thus, there must be a logger
service that I can use!

00:04:00.086 --> 00:04:02.166 align:middle
Quod erat demonstrandum!

00:04:02.536 --> 00:04:04.056 align:middle
Forgive me latin nerds.

00:04:04.516 --> 00:04:06.796 align:middle
The point is: if we want to log something,

00:04:06.796 --> 00:04:10.126 align:middle
we just need to find the
service that does that work.

00:04:10.786 --> 00:04:14.666 align:middle
Okay! Rerun the command but
search for log: Boom!

00:04:14.846 --> 00:04:19.556 align:middle
It found about 10 services, all
starting with Psr\Log\LoggerInterface.

00:04:20.216 --> 00:04:23.696 align:middle
We're going to talk about what these
other services are in the next tutorial.

00:04:24.196 --> 00:04:25.916 align:middle
For now, focus on the main one.

00:04:26.456 --> 00:04:30.466 align:middle
This tells me is that there is a
service in the container for a logger.

00:04:30.846 --> 00:04:34.986 align:middle
And to get it, we can autowire
it using this interface.

00:04:35.546 --> 00:04:36.796 align:middle
What does that mean?

00:04:37.376 --> 00:04:41.816 align:middle
In the controller method where we want
the logger, add an argument type-hinted

00:04:41.816 --> 00:04:45.806 align:middle
with LoggerInterface - hit
tab - then say $logger.

00:04:46.446 --> 00:04:50.516 align:middle
In this case, the name of the argument
isn't important: it could be anything.

00:04:50.896 --> 00:04:55.876 align:middle
What matters is that the LoggerInterface
- that corresponds to this use statement -

00:04:56.156 --> 00:05:01.556 align:middle
matches the Psr\Log\LoggerInterface
from debug:autowiring.

00:05:02.226 --> 00:05:03.026 align:middle
It's that simple!

00:05:03.296 --> 00:05:06.126 align:middle
Symfony will see this type-hint and say: Oh!

00:05:06.366 --> 00:05:09.446 align:middle
Since that type-hint matches the
autowiring type for this service,

00:05:09.686 --> 00:05:13.096 align:middle
they must want me to pass
them that service object.

00:05:13.576 --> 00:05:15.536 align:middle
I don't know why Symfony
sounds like a frog in my head.

00:05:16.026 --> 00:05:17.956 align:middle
Anyway, let's see if this works.

00:05:18.356 --> 00:05:23.796 align:middle
Add dd($logger): dd() stands for
"dump and die" and comes from Symfony.

00:05:24.526 --> 00:05:26.066 align:middle
Refresh! Yes!

00:05:26.126 --> 00:05:29.676 align:middle
It printed the object beautifully
then stopped execution.

00:05:30.096 --> 00:05:31.186 align:middle
It's working!

00:05:31.686 --> 00:05:37.196 align:middle
Symfony passes us a Monolog\Logger object,
which implements that LoggerInterface.

00:05:37.896 --> 00:05:42.756 align:middle
The trick we just did - called
autowiring - works in exactly two places:

00:05:43.226 --> 00:05:48.376 align:middle
our controller methods and the
__construct() method of any service.

00:05:48.756 --> 00:05:51.466 align:middle
We'll see that second situation
in the next chapter.

00:05:52.096 --> 00:05:55.256 align:middle
And if you're wondering where this Logger
service came from in the first place...

00:05:55.546 --> 00:05:56.666 align:middle
we already know the answer!

00:05:56.956 --> 00:05:58.196 align:middle
From a bundle.

00:05:58.586 --> 00:06:00.236 align:middle
In this case, MonologBundle.

00:06:00.816 --> 00:06:03.376 align:middle
And... how could we configure that service...

00:06:03.376 --> 00:06:06.086 align:middle
to, I don't know, log to a different file?

00:06:06.566 --> 00:06:10.026 align:middle
The answer is: config/packages/monolog.yaml.

00:06:10.766 --> 00:06:14.886 align:middle
This config - including this line
- configures MonologBundle...

00:06:15.176 --> 00:06:21.136 align:middle
which really means that it configures how
the services work that MonologBundle give us.

00:06:21.836 --> 00:06:24.786 align:middle
We'll learn about this percent
syntax in the next tutorial,

00:06:25.076 --> 00:06:28.956 align:middle
but this tells the Logger service
to log to this dev.log file.

00:06:29.706 --> 00:06:32.806 align:middle
Ok, now that we have the
Logger service, let's use it!

00:06:33.246 --> 00:06:36.696 align:middle
How? Well, of course, you can read the docs.

00:06:37.046 --> 00:06:39.906 align:middle
But thanks to the type-hint,
our editor will help us!

00:06:40.396 --> 00:06:42.756 align:middle
LoggerInterface has a bunch of methods.

00:06:43.086 --> 00:06:46.696 align:middle
Let's use -&gt;info() and say:
Starship collection retrieved.

00:06:48.086 --> 00:06:49.646 align:middle
Try it out: refresh.

00:06:50.126 --> 00:06:51.146 align:middle
The page worked...

00:06:51.296 --> 00:06:53.026 align:middle
but did it log anything?

00:06:53.426 --> 00:06:55.836 align:middle
We could go check the dev.log file.

00:06:56.376 --> 00:07:01.406 align:middle
Or, we can use the Log section
of the profiler for this request.

00:07:02.066 --> 00:07:03.036 align:middle
But... wait!

00:07:03.306 --> 00:07:04.986 align:middle
This is an API request...

00:07:05.156 --> 00:07:08.936 align:middle
so we don't have that cool web
debug toolbar on the bottom!

00:07:09.656 --> 00:07:10.576 align:middle
That's true...

00:07:11.116 --> 00:07:13.966 align:middle
but Symfony did still collect all that info!

00:07:14.726 --> 00:07:19.796 align:middle
To get to the profiler for this
request, change the URL to /_profiler.

00:07:20.496 --> 00:07:24.426 align:middle
This lists the most recent requests
to our app, with the newest on top.

00:07:24.846 --> 00:07:25.716 align:middle
See this one?

00:07:26.056 --> 00:07:28.106 align:middle
That's our API request from a minute ago!

00:07:28.556 --> 00:07:29.996 align:middle
If you click this token...

00:07:30.446 --> 00:07:36.126 align:middle
boom! We're looking at the profiler
for that API call in all its glory...

00:07:36.776 --> 00:07:38.446 align:middle
including a Log section...

00:07:38.686 --> 00:07:40.186 align:middle
with our message.

00:07:40.886 --> 00:07:45.636 align:middle
Ok, now that we've seen how to use a
service, let's create our own service next!

00:07:45.856 --> 00:07:47.296 align:middle
We're unstoppable!

