WEBVTT

NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com

00:00:01.056 --> 00:00:02.526 align:middle
One of the features on our site...

00:00:02.766 --> 00:00:04.066 align:middle
which doesn't work yet...

00:00:04.306 --> 00:00:07.656 align:middle
is that you can up and down
vote answers to a question.

00:00:08.456 --> 00:00:13.136 align:middle
Eventually, when you click up or
down, this will make an AJAX request

00:00:13.216 --> 00:00:15.716 align:middle
to an API endpoint that we will make.

00:00:16.236 --> 00:00:21.186 align:middle
That endpoint will save the vote to
the database and respond with JSON

00:00:21.376 --> 00:00:27.056 align:middle
that contains the new vote count so that
our JavaScript can update this vote number.

00:00:28.106 --> 00:00:29.986 align:middle
We don't have a database in our app yet,

00:00:30.366 --> 00:00:33.626 align:middle
but we're ready to build every
other part of this feature.

00:00:34.866 --> 00:00:40.616 align:middle
Let's start by creating a JSON API
endpoint that will be hit via AJAX

00:00:40.826 --> 00:00:43.276 align:middle
when a user up or down votes an answer.

00:00:44.106 --> 00:00:48.256 align:middle
We could create this in QuestionController
as a new method.

00:00:48.666 --> 00:00:54.066 align:middle
But since this endpoint really deals with a
"comment", let's create a new controller class.

00:00:56.106 --> 00:00:57.606 align:middle
Call it CommentController.

00:00:58.876 --> 00:01:04.306 align:middle
Like before, we're going to say
extends AbstractController and hit tab

00:01:04.476 --> 00:01:08.926 align:middle
so that PhpStorm autocompletes this
and adds the use statement on top.

00:01:08.926 --> 00:01:12.286 align:middle
Extending this class gives
us shortcut methods...

00:01:12.376 --> 00:01:14.766 align:middle
and I love shortcuts!

00:01:14.766 --> 00:01:16.836 align:middle
Inside, create a public function.

00:01:17.286 --> 00:01:18.506 align:middle
This could be called anything...

00:01:18.946 --> 00:01:20.666 align:middle
how about commentVote().

00:01:23.006 --> 00:01:27.406 align:middle
Add the route above: /**, then @Route.

00:01:28.126 --> 00:01:34.236 align:middle
Auto-complete the one from the Routing component
so that PhpStorm adds its use statement.

00:01:34.336 --> 00:01:43.606 align:middle
For the URL, how about /comments/{id}
- this will eventually be the id

00:01:43.606 --> 00:01:49.276 align:middle
of the specific comment in the
database - /vote/{direction},

00:01:51.136 --> 00:01:55.076 align:middle
where {direction} will either
be the word up or the word down.

00:01:56.106 --> 00:02:02.556 align:middle
And because we have these two wildcards, we
can add two arguments: $id and $direction.

00:02:03.876 --> 00:02:10.446 align:middle
I'll start with a comment: the $id will be
super important later when we have a database...

00:02:10.586 --> 00:02:12.846 align:middle
but we won't use it at all right now.

00:02:13.716 --> 00:02:16.836 align:middle
Without a database, we'll kinda fake the logic.

00:02:16.836 --> 00:02:24.106 align:middle
If $direction === 'up', then we would
normally save this up-vote to the database

00:02:24.346 --> 00:02:26.636 align:middle
and query for the new vote count.

00:02:27.346 --> 00:02:34.396 align:middle
Instead, say $currentVoteCount = rand(7, 100).

00:02:35.286 --> 00:02:38.586 align:middle
The vote counts in the template
are hardcoded to 6.

00:02:38.666 --> 00:02:44.496 align:middle
So this will make the new vote count appear
to be some random number higher than that.

00:02:45.336 --> 00:02:53.096 align:middle
In the else, do the opposite: a
random number between 0 and 5.

00:02:53.096 --> 00:02:56.926 align:middle
Yes, this will all be much
cooler when we have a database,

00:02:57.156 --> 00:02:59.516 align:middle
but it will work great for our purposes.

00:03:00.776 --> 00:03:05.066 align:middle
The question now is: after
"saving" the vote to the database,

00:03:05.376 --> 00:03:07.816 align:middle
what should this controller return?

00:03:08.656 --> 00:03:11.426 align:middle
Well it should probably return JSON...

00:03:11.806 --> 00:03:18.376 align:middle
and I know that I want to include the new vote
count in its data so our JavaScript can use

00:03:18.376 --> 00:03:20.916 align:middle
that to update the vote number text.

00:03:20.966 --> 00:03:24.526 align:middle
So... how do we return JSON?

00:03:25.356 --> 00:03:30.976 align:middle
Remember: our only job in a controller
is to return a Symfony Response object.

00:03:31.716 --> 00:03:38.216 align:middle
JSON is nothing more than a response whose
body is a JSON string instead of HTML.

00:03:39.036 --> 00:03:45.086 align:middle
So we could say: return new Response()
with json_encode() of some data.

00:03:45.796 --> 00:03:51.986 align:middle
But! Instead, return new
JsonResponse() - auto-complete this

00:03:52.116 --> 00:03:54.436 align:middle
so that PhpStorm adds the use statement.

00:03:55.216 --> 00:03:57.826 align:middle
Pass this an array with the data we want.

00:03:58.416 --> 00:04:01.956 align:middle
How about a votes key set to $currentVoteCount.

00:04:02.796 --> 00:04:05.816 align:middle
Now... you may be thinking: Ryan!

00:04:06.186 --> 00:04:10.476 align:middle
You keep saying that we must
return a Response object...

00:04:10.476 --> 00:04:13.356 align:middle
and you just returned something different.

00:04:13.696 --> 00:04:14.916 align:middle
This is madness!

00:04:15.036 --> 00:04:16.506 align:middle
Fair point.

00:04:17.056 --> 00:04:22.026 align:middle
But! If you hold Command or Ctrl
and click the JsonResponse class,

00:04:22.666 --> 00:04:26.776 align:middle
you'll learn that JsonResponse extends Response.

00:04:27.406 --> 00:04:31.946 align:middle
This class is nothing more than a
shortcut for creating JSON responses:

00:04:32.706 --> 00:04:39.416 align:middle
it JSON encodes the data we pass to it and
makes sure that the Content-Type header is set

00:04:39.416 --> 00:04:46.846 align:middle
to application/json, which helps AJAX libraries
understand that we're returning JSON data.

00:04:46.986 --> 00:04:52.496 align:middle
So... ah! Let's test out
our shiny-new API endpoint!

00:04:53.006 --> 00:04:58.866 align:middle
Copy the URL, open a new browser
tab, paste and fill in the wildcards:

00:04:59.246 --> 00:05:02.236 align:middle
how about 10 for {id} and vote "up".

00:05:02.986 --> 00:05:03.696 align:middle
Hit enter.

00:05:04.276 --> 00:05:06.236 align:middle
Hello JSON endpoint!

00:05:06.856 --> 00:05:11.276 align:middle
The big takeaway is this: JSON
responses are nothing special.

00:05:12.176 --> 00:05:15.256 align:middle
The JsonResponse class makes life easier...

00:05:15.756 --> 00:05:18.186 align:middle
but we can be even lazier!

00:05:18.186 --> 00:05:25.756 align:middle
Instead of new JsonResponse,
just say return $this-&gt;json().

00:05:25.756 --> 00:05:32.296 align:middle
That changes nothing: it's a shortcut method
to create the same JsonResponse object.

00:05:32.916 --> 00:05:33.886 align:middle
Easy peasy.

00:05:33.886 --> 00:05:41.486 align:middle
By the way, one of the "components" in Symfony
is called the "Serializer", and it's really good

00:05:41.486 --> 00:05:44.936 align:middle
at converting objects into JSON or XML.

00:05:45.636 --> 00:05:48.456 align:middle
We don't have it installed yet, but if we did,

00:05:48.946 --> 00:05:54.406 align:middle
the $this-&gt;json() would start using
it to serialize whatever we pass.

00:05:55.186 --> 00:05:58.586 align:middle
That wouldn't make any difference
in our case with an array,

00:05:59.196 --> 00:06:03.436 align:middle
but it means that you could start
passing objects to $this-&gt;json().

00:06:03.436 --> 00:06:09.726 align:middle
If you want to learn more - or want to build
a super-rich API - check out our tutorial

00:06:09.726 --> 00:06:15.606 align:middle
about API Platform: an amazing
Symfony bundle for building APIs.

00:06:15.676 --> 00:06:20.776 align:middle
Next, let's write some JavaScript that
will make an AJAX call to our new endpoint.

00:06:21.136 --> 00:06:27.546 align:middle
We'll also learn how to add global Javascript
as well as page-specific JavaScript.

