You're Killing it!
Let's do something fun, like create a custom page. Like always, any custom code will
live in a module. And modules live in the
modules/ directory. Create a new one
dino_roar. To make Drupal fall in love with your module, create the info
dino_roar.info.yml. If you loved the old
.info files, then you'll feel
all warm and fuzzy with these: it's the same thing, but now in the YAML format.
Inside give it a
Dino ROAR, a
Roar at you,
|name: Dino ROAR|
|description: "ROOOOOAR at you"|
If YAML is new to you, cool! It's pretty underwhelming: just a colon separated key-value pair. But make sure you have at least one space after the colon. Yaml also supports hierarchies of data via indentation - but there's none of that in this file.
Module ready! Head back to the browser and go into the "Extend" section. With any luck we'll see the module here. There it is under "Sample": "Dino ROAR". It sounds terrifying. Check the box and press the install button anyways. What's the worst that could happen?
Nothing! But now we can build that page I keep talking about.
In any modern framework - and I am including Drupal in this category, yay! - creating a page is two steps. First, define the URL for the page via a route. That's your first buzzword in case you're writing things down.
Second, create a controller for that page. This is a function that you'll write that actually builds the page. It's also another buzzword: controller.
If these are new buzzwords for you, that's ok - they're just a new spin on some old ideas.
For step 1, create a new file in the module:
dino_roar.routing.yml. Create a new
dino_says: this is the internal name of the route and it isn't important
|... lines 2 - 7|
Go in 4 spaces - or 2 spaces, it doesn't matter, just be consistent - and add
a new property to this route called
path. Set it to
/the/dino/says: the URL to
the new page:
|... lines 3 - 7|
path, a few more route properties are needed. The first, is
_controller key beneath it:
|... lines 5 - 7|
_controller key tells Drupal which function should be called when someone
goes to the URL for this exciting page. Set this to
This is a namespaced class followed by
:: and then a method name. We'll create
this function in a second.
Also add a
requirements key with a
_permission key set to
|... lines 2 - 4|
|_permission: 'access content'|
We won't talk about permissions now, but this is what will allow us to view the page.
In YAML, you usually don't need quotes, except in some edge cases with special
characters. But it's always safe to surround values with quotes. So if you're in
doubt, use quotes! I don't need them around
access content... but it makes me fee
Step 1 complete: we have a route. For Step 2, we need to create the controller: the
function that will actually build the page. Inside of the
dino_roar module create
src directory and then a
Controller directory inside of that. Finally, add
a new PHP class called
|... lines 2 - 14|
Ok, stop! Fun fact: every class you create will have a namespace at the top. If you're not comfortable with namespaces, they're really easy. So easy that we teach them to you in 120 seconds in our namespaces tutorial. So pause this video, check that out and then everything we're about to do will seem much more awesome.
But you can't just set the namespace to any old thing: there are rules. It must
Drupal\, then the name of the module -
dino_roar\, then whatever directory
or directories this file lives in after
src/. This class lives in
Your class name also has to match the filename, +
|... lines 4 - 6|
|... lines 9 - 12|
If you mess any of this up, Drupal isn't going to be able to find your class.
The full class name is now
Drupal\dino_roar\Controller\RoarController. Hey, this
conveniently matches the
_controller of our route!
RoarController, add the new
public function roar():
|... lines 1 - 6|
|public function roar()|
|... line 11|
Now, you might be asking yourself what a controller function like this should return.
And to that I say - excellent question! Brilliant! A controller should always return
Response object. Ok, that's not 100% true - but let me lie for just a
little bit longer.
The code-styling (4 spces indentation, etc) I'm using is called PSR-4. It's a great PHP standard, but is (I admit) different than the recommended Drupal standard.
To return a response, say
return new Response(). I'll let it autocomplete the
Response class from Symfony's HttpFoundation namespace. When I hit tab to select this,
PhpStorm adds the
use statement to the top of the class automatically:
|... lines 1 - 4|
|public function roar()|
|return new Response('ROOOOOAR!');|
That's important: whenever you reference a class, you must add a
for it. If you forget, you'll get the famous "Class Not Found" error.
For the page content, we will of course
That's it! That's everything. Go to your browser and head to
Hmm page not found. As a seasoned Drupal developer, you may be wondering, "uhh do I need to clear some cache?" My gosh, you're right!