Let's create a "show page" for ships: a page that displays the details for just one ship.
The homepage lives in MainController.
And so we could add another route and method here.
But as my site grows, I'm probably going to have multiple pages related
to starships: maybe to edit and delete them.
So instead, in the Controller/ directory, create a new class.
Call it StarshipController, and, as usual, extend AbstractController.
Inside, let's get to work!
Add a public function called show(), I'll add the Response return type, then the route,
with /starships/ and a wildcard called {id}.
And again, it's optional, but I'll be fancy and add the \d+
so the wildcard only matches a number.
Now, because we have an {id} wildcard, we are allowed to have an $id argument down here.
dd($id) to see how we're doing so far.
Try it. Head to /starships/2.
Lovely! Now we're going to do something familiar: take this $id
and query our imaginary database for the matching Starship.
The key to doing this is our StarshipRepository service and its helpful find() method.
In the controller, add a StarshipRepository $repository argument...
then say $ship equals $repository->find($id).
And if not $ship, trigger a 404 page
with throw $this->createNotFoundException() and starship not found.
Cool! At the bottom, instead of returning JSON, render a template: return $this->render()
and follow the standard naming convention for templates: starship/show.html.twig.
Pass this one variable: $ship.
Controller, check!
Next, in the templates/ directory,
we could create a starship/ directory and show.html.twig inside.
But I want to show you a shortcut from the Symfony PhpStorm plugin.
Click on the template name, press Alt+Enter and...
check it out!
On top it says "Twig: Create Template".
Confirm the path and boom!
We've got our new template!
It's... hiding over here.
There it is: starship/show.html.twig.
Pretty much every template starts the same: {% extend 'base.html.twig' %}...
then override some blocks!
Override title...
and this time, let's use that ship variable: ship.name.
Finish with endblock.
And for the main content, add the block body...
endblock and put an h1 inside.
Print ship.name again and...
I'll paste in a table with some info.
Nothing special here: we're just printing basic ship data.
When we try the page...
it's alive!
Next question: from the homepage, how could we add a link to the new ship show page?
The most obvious option is to hardcode the URL, like /starships/ then the id.
But there's a better way.
Instead, we're going to tell Symfony: Hey, I want to generate a URL to this route.
The advantage is that if we decide later to change the URL of this route,
every link to this will update automatically.
Let me show you.
Find your terminal and run: php bin/console debug:router I haven't mentioned it yet,
but every route has an internal name.
Right now, they're being auto-generated by Symfony, which is fine.
But as soon as you want to generate a URL to a route, we should take control
of that name to make sure it never changes.
Find the show page route and add a name key.
I'll use app_starship_show.
The name could be anything, but this is the convention I follow: app because it's a route
that I'm making in my app, then the controller class name and method name.
Naming a route doesn't change how it works.
But it does let us generate a URL to it.
Open up templates/main/homepage.html.twig.
Down here, turn the ship name into a link.
I'll put this onto multiple lines and add an a tag with href="".
To generate the URL, say {{ path() }} and pass it the name of the route.
I'll put the closing tag on the other side.
If we stop now, this won't quite work.
On the homepage: Some mandatory parameters are missing - id -
to generate a URL for route app_starship_show.
That makes sense!
We're telling Symfony: Howdy!
I want to generate a URL to this route.
Symfony then responds: Cool...
except that this route has a wildcard in it.
So like...
what do you want me to put in the URL for the id part?
When there's a wildcard in the route, we need to add a second argument to path() with {}.
This is Twig's associative array syntax.
So it's exactly like JavaScript: it's a key-value pair list.
Pass id set to myShip.id.
And now...
got it! Look at that URL: /starships/3.
Alrighty, our site is still ugly.
It's time to start fixing that by bringing in Tailwind CSS and learning
about Symfony's AssetMapper component.