WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.086 --> 00:00:04.706 align:middle
If you want to build an API, you
can absolutely do that with Symfony.

00:00:05.216 --> 00:00:10.386 align:middle
In fact, it's a fantastic option
in part, because of API Platform.

00:00:10.896 --> 00:00:14.266 align:middle
That's a framework for creating
APIs built on top of Symfony

00:00:14.416 --> 00:00:16.796 align:middle
that both makes building your API fast

00:00:16.976 --> 00:00:20.766 align:middle
and creates an API that's more
robust than you could imagine.

00:00:21.196 --> 00:00:24.196 align:middle
But, it's also simple enough to
return JSON from a controller.

00:00:24.636 --> 00:00:27.426 align:middle
Let's see if we can return
some ship data as JSON.

00:00:28.096 --> 00:00:29.956 align:middle
This will be our second page.

00:00:30.126 --> 00:00:34.596 align:middle
Well, it's really an "endpoint", but this
will be our second route &amp; controller combo.

00:00:35.226 --> 00:00:38.536 align:middle
In MainController, we could
add another method here.

00:00:38.966 --> 00:00:43.016 align:middle
But for organization, let's create
a totally new controller class.

00:00:43.706 --> 00:00:47.986 align:middle
I'll go to New -&gt; PHP Class and
call it StarshipApiController.

00:00:48.826 --> 00:00:53.596 align:middle
Because I went to New -&gt; PHP Class, it
created the class and the namespace for me.

00:00:53.926 --> 00:00:54.706 align:middle
Super nice!

00:00:55.246 --> 00:00:58.466 align:middle
Also, going forward, each
time I create a controller,

00:00:58.646 --> 00:01:01.296 align:middle
I'll immediately extend AbstractController...

00:01:01.826 --> 00:01:05.066 align:middle
because those shortcuts are
nice and there's no downside.

00:01:05.756 --> 00:01:07.626 align:middle
Add a public function getCollection()

00:01:07.736 --> 00:01:11.036 align:middle
because this will return info
about a collection of starships.

00:01:11.586 --> 00:01:15.406 align:middle
And, like always, you can add the
Response return type or skip it.

00:01:15.986 --> 00:01:18.796 align:middle
Above this, add the route with #[Route()].

00:01:19.286 --> 00:01:21.566 align:middle
Select the one from Attribute and hit tab.

00:01:22.286 --> 00:01:25.036 align:middle
So I just used auto-completion
to add the use statements

00:01:25.036 --> 00:01:28.386 align:middle
for AbstractController, Route, and Response.

00:01:28.596 --> 00:01:30.406 align:middle
Make sure you have all of those.

00:01:30.936 --> 00:01:34.226 align:middle
For the URL, how about /api/starships.

00:01:35.056 --> 00:01:39.076 align:middle
Inside, I'll paste a $starships
variable that's set to an array

00:01:39.246 --> 00:01:42.346 align:middle
of three associative arrays of starship data.

00:01:43.196 --> 00:01:45.816 align:middle
You can probably imagine
how this will look as JSON.

00:01:46.396 --> 00:01:48.136 align:middle
How do we turn it into JSON?

00:01:48.596 --> 00:01:54.536 align:middle
Well, it can be this simple: return new
Response with json_encode($starships).

00:01:55.146 --> 00:01:56.896 align:middle
But we can do better!

00:01:57.226 --> 00:02:00.736 align:middle
Instead, return $this-&gt;json($starships).

00:02:01.446 --> 00:02:02.376 align:middle
Let's try it!

00:02:02.766 --> 00:02:06.376 align:middle
Find your browser and head to /api/starships.

00:02:06.956 --> 00:02:08.496 align:middle
Dang, that was easy.

00:02:09.026 --> 00:02:13.216 align:middle
If you're wondering why the JSON is styled
and looks cool, that's not a Symfony thing.

00:02:13.216 --> 00:02:16.406 align:middle
I have a Chrome extension
installed called JSONVue.

00:02:17.176 --> 00:02:21.606 align:middle
Now in the real world, when we start querying
the database, we're going to be working

00:02:21.606 --> 00:02:24.666 align:middle
with objects, not associative arrays.

00:02:25.306 --> 00:02:29.256 align:middle
We won't add a database in this
tutorial, but we can start using objects

00:02:29.256 --> 00:02:31.516 align:middle
for our data to make things more realistic.

00:02:32.076 --> 00:02:35.696 align:middle
In the src/ directory, create a
new subdirectory called Model.

00:02:36.536 --> 00:02:41.506 align:middle
Ok, important thing: what we're about to do
has absolutely nothing to do with Symfony.

00:02:41.886 --> 00:02:45.006 align:middle
I'm simply looking at this array
and thinking: You know what?

00:02:45.296 --> 00:02:50.936 align:middle
Instead of passing around this associative array
with name, class, captain, and status keys,

00:02:51.216 --> 00:02:54.926 align:middle
I'd rather have a Starship
class and pass around objects.

00:02:55.356 --> 00:03:01.296 align:middle
So entirely on my own, independent of Symfony,
I've decided to create a Model directory -

00:03:01.616 --> 00:03:05.636 align:middle
this could be called anything - and
inside a new class called Starship.

00:03:06.486 --> 00:03:12.446 align:middle
And because this class is just to help us,
we get to make it look however we want,

00:03:12.876 --> 00:03:15.216 align:middle
and it doesn't need to extend any base class.

00:03:15.866 --> 00:03:21.556 align:middle
Create a public function __construct()
with five properties: a private int $id,

00:03:22.036 --> 00:03:26.066 align:middle
then four more properties for each of
the four keys that we have in the array:

00:03:26.876 --> 00:03:29.716 align:middle
private string $name, private string $class,

00:03:30.336 --> 00:03:33.796 align:middle
private string $captain and
private string $status.

00:03:35.026 --> 00:03:39.466 align:middle
Oh, and my editor is highlighting this
file because we installed PHP-CS-Fixer

00:03:39.646 --> 00:03:42.196 align:middle
and that found a code style violation.

00:03:42.666 --> 00:03:47.696 align:middle
I can click this to fix it or go here
and hit Alt+Enter to do the fix there.

00:03:47.966 --> 00:03:49.196 align:middle
Super nice!

00:03:49.826 --> 00:03:54.026 align:middle
Anyway, if you're not familiar with this
constructor syntax, this creates a constructor

00:03:54.026 --> 00:03:59.536 align:middle
with five arguments and, at the same time,
creates five properties that will be set

00:03:59.536 --> 00:04:01.986 align:middle
to whatever we pass to these arguments.

00:04:02.626 --> 00:04:05.306 align:middle
But, because I decided to
make these properties private,

00:04:05.656 --> 00:04:08.726 align:middle
if we did instantiate a new Starship object...

00:04:08.996 --> 00:04:11.586 align:middle
we wouldn't be able to read any of the data!

00:04:12.336 --> 00:04:14.926 align:middle
To allow that, we can create getter methods.

00:04:15.396 --> 00:04:16.796 align:middle
But, I'm not going to do this by hand.

00:04:17.146 --> 00:04:21.636 align:middle
Instead, go to the Code -&gt; Generate
menu option - or Cmd + N on a Mac -

00:04:21.936 --> 00:04:25.366 align:middle
select getters then generate
a getter for every property.

00:04:26.246 --> 00:04:29.846 align:middle
Nice! Five shiny new, public getter method.

00:04:30.656 --> 00:04:36.466 align:middle
Ok, back in our controller, let's convert these
arrays to objects: new Starship() - hit tab,

00:04:36.466 --> 00:04:40.646 align:middle
so it adds the use statement - then
give this an id of, how about, 1...

00:04:41.176 --> 00:04:49.256 align:middle
and transfer the other values for name,
class, captain, and finally status.

00:04:50.316 --> 00:04:53.066 align:middle
And just like that, we have our first object!

00:04:53.696 --> 00:04:57.356 align:middle
I'll highlight the other two arrays and
paste in the two objects to save time.

00:04:58.156 --> 00:05:01.306 align:middle
We now have an array of 3 Starship objects...

00:05:01.306 --> 00:05:02.636 align:middle
which feels nicer.

00:05:03.006 --> 00:05:05.596 align:middle
And we're passing those to $this-&gt;json().

00:05:06.086 --> 00:05:07.836 align:middle
Is that still going to work?

00:05:08.216 --> 00:05:09.466 align:middle
Totally not!

00:05:09.856 --> 00:05:12.426 align:middle
We get an array of three empty objects!

00:05:12.816 --> 00:05:19.026 align:middle
That's because, internally, $this-&gt;json()
uses the PHP json_encode() function...

00:05:19.286 --> 00:05:22.186 align:middle
and that function can't handle
private properties.

00:05:22.726 --> 00:05:26.276 align:middle
What we need is something smarter:
something that can recognize that,

00:05:26.486 --> 00:05:30.506 align:middle
even though the name property is
private, we have a public getName() method

00:05:30.506 --> 00:05:33.016 align:middle
that can be called to read
that property's value.

00:05:33.666 --> 00:05:35.566 align:middle
Is there a tool that does that?

00:05:36.036 --> 00:05:40.326 align:middle
Well, remember how Symfony is a huge set of
components that solve individual problems?

00:05:40.826 --> 00:05:45.186 align:middle
One component is called serializer,
and its whole job is

00:05:45.186 --> 00:05:47.936 align:middle
to take objects and serialize them to JSON...

00:05:48.286 --> 00:05:52.536 align:middle
or take JSON and deserialize
that back into objects.

00:05:52.936 --> 00:05:54.966 align:middle
And it can totally handle situations

00:05:54.966 --> 00:05:58.266 align:middle
where you have private properties
with public getter methods.

00:05:58.656 --> 00:06:00.506 align:middle
So let's get it installed!

00:06:00.856 --> 00:06:07.986 align:middle
composer require serializer And once
more folks, yes, this is an alias...

00:06:08.066 --> 00:06:10.096 align:middle
and it's an alias to a pack.

00:06:10.526 --> 00:06:15.536 align:middle
This pack installs the symfony/serializer
package as well as a few others

00:06:15.536 --> 00:06:18.086 align:middle
that make it work in a really robust way.

00:06:18.846 --> 00:06:24.296 align:middle
Now, without doing anything else,
go back, refresh, and it works?

00:06:24.516 --> 00:06:29.096 align:middle
How? It turns out that the
$this-&gt;json() method is smart.

00:06:29.556 --> 00:06:36.006 align:middle
To peek at it, hold Command on a Mac or Ctrl on
other machines and click the method name to jump

00:06:36.006 --> 00:06:38.566 align:middle
into the core Symfony file where this lives.

00:06:39.436 --> 00:06:42.876 align:middle
Ah! The code here won't make total sense yet,

00:06:43.166 --> 00:06:46.746 align:middle
but it detects if the serializer
system is available....

00:06:46.996 --> 00:06:51.286 align:middle
and if it is, uses that to
transform the object to JSON.

00:06:51.916 --> 00:06:55.096 align:middle
But, what do I mean by "serializer
system" exactly?

00:06:55.416 --> 00:06:57.796 align:middle
And what is the serializer key...

00:06:58.076 --> 00:07:00.126 align:middle
inside this container thing?

00:07:00.686 --> 00:07:04.966 align:middle
Or, what if we needed to transform an object
to JSON somewhere other than our controller...

00:07:05.086 --> 00:07:07.946 align:middle
where we don't have access
to the -&gt;json() shortcut?

00:07:08.446 --> 00:07:11.366 align:middle
How could we access the serializer
system from there?

00:07:12.046 --> 00:07:17.136 align:middle
Friends, it's time to learn about the most
important concept in Symfony: services.

