If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
Ok, you're a configuration pro: you know where services come from and how to configure them. Here's our question: where do routes come from? And can third party bundles give us more routes?
The answer is, no :(. Ah, I'm kidding - they totally can. In fact, find your terminal and run:
./bin/console debug:router
Surprise! There are a lot more than just the two routes that we've created. Where are these coming from?
Answer time: when Symfony loads the route list, it only loads one routing file.
In the dev
environment, it loads routing_dev.yml
:
_wdt: | |
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" | |
prefix: /_wdt | |
_profiler: | |
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" | |
prefix: /_profiler | |
_errors: | |
resource: "@TwigBundle/Resources/config/routing/errors.xml" | |
prefix: /_error | |
_main: | |
resource: routing.yml |
In all environments, it loads routing.yml
:
app: | |
resource: "@AppBundle/Controller/" | |
type: annotation | |
... lines 4 - 9 |
Inside routing_dev.yml
, we're importing additional routes from WebProfilerBundle
and the TwigBundle
:
_wdt: | |
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" | |
prefix: /_wdt | |
_profiler: | |
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" | |
prefix: /_profiler | |
_errors: | |
resource: "@TwigBundle/Resources/config/routing/errors.xml" | |
prefix: /_error | |
... lines 12 - 15 |
That's why there are extra routes in debug:router
. This also imports routing.yml
at the bottom to load all the main routes:
... lines 1 - 12 | |
_main: | |
resource: routing.yml |
You can really import anything you want: you're in complete control of what routes you import from a bundle. These files are usually XML, but that doesn't make any difference.
In the main routing.yml
, there's yet another import:
app: | |
resource: "@AppBundle/Controller/" | |
type: annotation | |
... lines 4 - 9 |
We're out of control! This loads annotation routes from the controllers in our bundle.
But you can also create routes right inside YAML - a lot of people actually prefer this over annotations. The difference is purely preference: there's no performance impact to either.
Tip
In a big project, there is actually some performance impact in the dev
environment
for using annotations.
Let's create a homepage route: use the key homepage
- that's its name. Then add
path
set to just /
:
... lines 1 - 4 | |
homepage: | |
path: / | |
... lines 7 - 9 |
Now, we need to point this route to a controller: the function that will render it.
Doing this in yml
is a bit more work. Add a defaults
key and an _controller
key
below that. Set this to AppBundle:Main:homepage
:
... lines 1 - 4 | |
homepage: | |
path: / | |
defaults: | |
_controller: AppBundle:Main:homepage |
Yes yes, this looks totally weird - this is a Symfony-specific shortcut. It means that we
will have a controller in AppBundle
called MainController
with a method named
homepageAction()
.
In the Controller
directory, create that new MainController
class:
... lines 1 - 2 | |
namespace AppBundle\Controller; | |
use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
class MainController extends Controller | |
{ | |
... lines 9 - 12 | |
} |
Next add public function homepageAction()
. Make this class extend Symfony's base Controller
so that we can access the render()
function. Set it to render main/homepage.html.twig
without passing any variables:
... lines 1 - 6 | |
class MainController extends Controller | |
{ | |
public function homepageAction() | |
{ | |
return $this->render('main/homepage.html.twig'); | |
} | |
} |
Create this real quick in app/Resources/views
: new file, main/homepage.html.twig
:
{% extends 'base.html.twig' %} | |
{% block body %} | |
... line 4 | |
{% endblock %} |
Templates basically always look the same: extend the base template - base.html.twig
-
and then override one or more of its blocks. Override block body
: the block that
holds the main content in base.html.twig
.
Add some content to greet the aquanauts:
... lines 1 - 2 | |
{% block body %} | |
<h1 class="page-header text-center">Welcome Aquanauts!</h1> | |
{% endblock %} |
Done! Before trying this, head over to the terminal and run:
./bin/console debug:router
There it is! There are many ways to define a route, but the result is exactly the
same. Refresh the browser. Thank you yml
for that lovely brand new route.
Woh guys. This course was a serious step forward. In the next parts, we're going to start adding big features: like talking to a database, forms, security and more. And when we do, I've got some exciting news: because of your work here, it's all going to make sense. Let's keep going and get really productive with Symfony.
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.1.*", // v3.1.4
"doctrine/orm": "^2.5", // v2.7.2
"doctrine/doctrine-bundle": "^1.6", // 1.6.4
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // 2.11.1
"symfony/polyfill-apcu": "^1.0", // v1.2.0
"sensio/distribution-bundle": "^5.0", // v5.0.22
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"knplabs/knp-markdown-bundle": "^1.4" // 1.4.2
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.7
"symfony/phpunit-bridge": "^3.0" // v3.1.3
}
}