WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.066 --> 00:00:06.126 align:middle
We know that services do work, and we know that
Symfony is full of services that we can use.

00:00:06.126 --> 00:00:12.336 align:middle
If you run: php bin/console debug:autowiring
We get the dinner menu of services,

00:00:12.456 --> 00:00:16.026 align:middle
where you can order any of these
by adding an argument type-hinted

00:00:16.026 --> 00:00:17.736 align:middle
with the matching class or interface.

00:00:18.186 --> 00:00:21.516 align:middle
We, of course, also do work in our code...

00:00:21.886 --> 00:00:22.366 align:middle
hopefully.

00:00:22.886 --> 00:00:27.906 align:middle
Right now, all that work is being done inside
our controller, like creating the Starship data.

00:00:28.616 --> 00:00:31.116 align:middle
Sure, this is hard-coded right now, but imagine

00:00:31.116 --> 00:00:34.406 align:middle
if this were real work: like
a complex database query.

00:00:34.956 --> 00:00:37.666 align:middle
Putting the logic inside a controller is "ok"...

00:00:37.826 --> 00:00:41.546 align:middle
but what if we wanted to reuse
this code somewhere else?

00:00:41.546 --> 00:00:45.236 align:middle
What if, on our homepage, we
wanted to get a dynamic count

00:00:45.236 --> 00:00:47.606 align:middle
of the Starships by grabbing this same data?

00:00:48.286 --> 00:00:51.396 align:middle
To do that, we need to move
this "work" into its own service

00:00:51.476 --> 00:00:54.056 align:middle
that both controllers could then use.

00:00:54.056 --> 00:00:56.886 align:middle
In the src/ directory, create
a new Repository directory

00:00:57.316 --> 00:01:00.266 align:middle
and a new PHP class inside
called StarshipRepository.

00:01:01.186 --> 00:01:03.456 align:middle
Just like when we built our Starship class,

00:01:03.776 --> 00:01:06.826 align:middle
this new class has absolutely
nothing to do with Symfony.

00:01:07.146 --> 00:01:11.496 align:middle
It's just a class that we've decided
to create to organize our work.

00:01:12.046 --> 00:01:16.836 align:middle
And so, Symfony doesn't care what it's
called, where it lives or what it looks like.

00:01:17.216 --> 00:01:21.466 align:middle
I called it StarshipRepository and
put it in a Repository directory

00:01:21.626 --> 00:01:25.636 align:middle
because that's a common programming
name for a class whose "work" is

00:01:25.636 --> 00:01:28.296 align:middle
to fetch a type of data, like Starship data.

00:01:28.996 --> 00:01:33.706 align:middle
Ok, before we even do anything in here, let's
see if we can use this inside a controller.

00:01:34.126 --> 00:01:35.346 align:middle
And, good news!

00:01:35.656 --> 00:01:39.706 align:middle
Just by creating this class, it's
already available for autowiring.

00:01:40.396 --> 00:01:46.466 align:middle
Add a StarshipRepository $repository argument,
and, to make sure it's working, dd($repository).

00:01:47.436 --> 00:01:50.436 align:middle
All right, spin over, click
back to our endpoint, and...

00:01:50.756 --> 00:01:53.266 align:middle
got it. That's so cool!

00:01:53.266 --> 00:02:01.026 align:middle
Symfony saw the StarshipRepository type-hint,
instantiated that object, then passed it to us.

00:02:01.026 --> 00:02:02.506 align:middle
Delete the dd()...

00:02:02.506 --> 00:02:04.706 align:middle
and let's move the starship data inside.

00:02:05.056 --> 00:02:05.606 align:middle
Copy it...

00:02:05.956 --> 00:02:08.956 align:middle
and create a new public function
called, how about, findAll().

00:02:10.446 --> 00:02:14.116 align:middle
Inside, return, then paste.

00:02:14.166 --> 00:02:16.746 align:middle
Back over in StarshipApiController,
delete that...

00:02:17.196 --> 00:02:23.146 align:middle
and it's beautifully simple:
$starships = $repository-&gt;findAll().

00:02:23.146 --> 00:02:26.296 align:middle
Done! When we try it, it still works...

00:02:26.496 --> 00:02:29.676 align:middle
and now the code for fetching
starships is nicely organized

00:02:29.676 --> 00:02:32.816 align:middle
into its own class and reusable across our app.

00:02:33.486 --> 00:02:36.836 align:middle
With that victory under our belt,
let's doing something harder.

00:02:37.186 --> 00:02:40.196 align:middle
What if, from inside StarshipRepository,

00:02:40.486 --> 00:02:44.936 align:middle
we needed access to another
service to help us do our work?

00:02:45.586 --> 00:02:46.226 align:middle
No problem!

00:02:46.516 --> 00:02:48.116 align:middle
We can use autowiring!

00:02:48.116 --> 00:02:51.096 align:middle
Let's try to autowire the logger service again.

00:02:51.716 --> 00:02:56.216 align:middle
The only difference this time is that we're
not going to add the argument to findAll().

00:02:56.856 --> 00:02:58.326 align:middle
I'll explain why in a minute.

00:02:58.326 --> 00:03:02.466 align:middle
Instead, add a new public function __construct()

00:03:02.466 --> 00:03:06.646 align:middle
and do the auto-wiring there:
private LoggerInterface $logger.

00:03:08.286 --> 00:03:12.376 align:middle
Down below, to use it, copy the code
from our controller, delete that,

00:03:12.976 --> 00:03:16.906 align:middle
paste it here, and update it to $this-&gt;logger.

00:03:17.796 --> 00:03:22.246 align:middle
Cool! Over in the controller, we can remove that
argument because we're not using it anymore.

00:03:22.246 --> 00:03:24.566 align:middle
Testing time!

00:03:24.956 --> 00:03:27.866 align:middle
Refresh! No error - that's a good sign.

00:03:28.396 --> 00:03:35.926 align:middle
To see if it logged something, go to /_profiler,
click on the top request, Logs, and...

00:03:36.256 --> 00:03:37.506 align:middle
there it is!

00:03:37.506 --> 00:03:41.686 align:middle
So let me explain why we added the
service argument to the constructor.

00:03:41.686 --> 00:03:46.936 align:middle
If we want to fetch a service - like the
logger, a database connection, whatever,

00:03:47.216 --> 00:03:54.176 align:middle
this is the correct way to use autowiring: add
a __construct method inside another service.

00:03:54.816 --> 00:03:59.666 align:middle
The trick we saw earlier - where we add
the argument to a normal method - yeah,

00:03:59.756 --> 00:04:03.676 align:middle
that's special and only works
for controller methods.

00:04:04.116 --> 00:04:06.596 align:middle
It's an extra convenience
that was added to the system.

00:04:07.086 --> 00:04:09.496 align:middle
It's a great feature, but the constructor way...

00:04:09.866 --> 00:04:12.726 align:middle
that's how autowiring really works.

00:04:12.726 --> 00:04:15.736 align:middle
And this "normal" way, it
even works in a controller.

00:04:16.196 --> 00:04:18.316 align:middle
You could add a __construct() method

00:04:18.456 --> 00:04:21.676 align:middle
with an autowirable argument
and that would totally work.

00:04:22.296 --> 00:04:25.526 align:middle
The point is: if you are in
a controller method, sure,

00:04:25.736 --> 00:04:28.406 align:middle
add the argument to the method - it's nice!

00:04:28.926 --> 00:04:32.326 align:middle
Just remember that it's a special
thing that only works here.

00:04:32.836 --> 00:04:35.396 align:middle
Everywhere else, autowire
through the constructor.

00:04:36.126 --> 00:04:39.056 align:middle
Let's celebrate our new service
by using it on the homepage.

00:04:39.456 --> 00:04:40.736 align:middle
Open up MainController.

00:04:41.386 --> 00:04:45.156 align:middle
This hardcoded $starshipCount
is so 30 minutes ago.

00:04:45.656 --> 00:04:48.766 align:middle
Autowire StarshipRepository $starshipRepository,

00:04:49.346 --> 00:04:54.896 align:middle
then say $ships = $starshipRepository-&gt;findAll()
and count them with count().

00:04:56.216 --> 00:04:59.396 align:middle
While we're here, instead of
this hardcoded $myShip array,

00:04:59.686 --> 00:05:02.356 align:middle
let's grab a random Starship object.

00:05:03.276 --> 00:05:09.916 align:middle
We can do that by saying $myShip equals
$ships[array_rand($ships)] Let's try it!

00:05:10.246 --> 00:05:12.656 align:middle
Hunt down your browser and head to the homepage.

00:05:13.286 --> 00:05:18.796 align:middle
Got it! We see the randomly changing ship down
here, and the correct ship number up here...

00:05:19.096 --> 00:05:21.416 align:middle
because we're multiplying
it by 10 in the template.

00:05:22.096 --> 00:05:24.146 align:middle
And something crazy-cool just happened!

00:05:24.546 --> 00:05:27.936 align:middle
A minute ago, myShip was an associative array.

00:05:28.226 --> 00:05:31.446 align:middle
But we changed it to be a Starship object.

00:05:31.926 --> 00:05:34.856 align:middle
And yet, the code on our page kept working.

00:05:35.336 --> 00:05:37.956 align:middle
We just accidentally saw a superpower of Twig.

00:05:38.636 --> 00:05:42.606 align:middle
Head to templates/main/homepage.html.twig
and scroll down to the bottom.

00:05:43.406 --> 00:05:46.586 align:middle
When you say myShip.name, Twig is really smart.

00:05:47.126 --> 00:05:50.746 align:middle
If myShip is an associative
array, it'll grab the name key.

00:05:50.746 --> 00:05:56.226 align:middle
If myShip is an object, like it is
now, it will grab the name property.

00:05:56.926 --> 00:05:59.616 align:middle
But even more than that,
if you look at Starship,

00:05:59.786 --> 00:06:03.896 align:middle
the name property is private,
so we can't access it directly.

00:06:04.396 --> 00:06:05.916 align:middle
Twig realizes that.

00:06:06.536 --> 00:06:09.286 align:middle
It looks at the name property,
sees that it's private,

00:06:09.556 --> 00:06:13.036 align:middle
but also sees that there's a public getName().

00:06:13.456 --> 00:06:15.526 align:middle
And so, it calls that.

00:06:16.326 --> 00:06:18.696 align:middle
All we need to say is myShip.name...

00:06:18.926 --> 00:06:22.836 align:middle
and Twig handles the details of
how to fetch that, which I love.

00:06:23.636 --> 00:06:25.296 align:middle
Ok, one last tiny tweak.

00:06:25.296 --> 00:06:30.346 align:middle
Instead of passing the starshipCount into our
template, we can do the count inside Twig.

00:06:30.926 --> 00:06:35.976 align:middle
Delete this variable, and
instead, pass a ships variable.

00:06:37.616 --> 00:06:43.236 align:middle
In the template, there we go, for the
count, we can say ships, which is an array,

00:06:43.476 --> 00:06:47.466 align:middle
and then use a Twig filter: |length.

00:06:47.466 --> 00:06:48.376 align:middle
That feels good.

00:06:48.746 --> 00:06:49.976 align:middle
Let's do the same thing down here...

00:06:49.976 --> 00:06:53.696 align:middle
and change it to greater than 2.

00:06:54.506 --> 00:06:56.066 align:middle
Try that out.

00:06:56.066 --> 00:06:58.036 align:middle
Our site just keeps working!

00:06:58.036 --> 00:07:03.536 align:middle
Next up: let's create more pages and learn
how to make routes that are even smarter.

