Drupal, like other web applications, receives an HTTP request for a resource and returns a response. This is a multi-step process that involves decoding the request and mapping it to a predefined callback. When the callback function is executed, the requested resource is prepared and returned to the caller.
Let us take a closer look at the way a simple page is built and displayed in both Drupal 7 and 8.
Drupal 7
In a module, for example simple_page_demo
, we implement a hook_menu
function as follows:
// simple_page_demo.module
/**
* Implements hook_menu().
*/
function simple_page_demo_menu() {
$items = array();
$items['simple-page-demo'] = array(
'title' => 'Simple page demo',
'description' => 'Demonstrates building a simple page',
'page callback' => 'simple_page_demo_output',
'access arguments' => array('access content'),
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
The key to the $items
array is the path to the page (/simple-page-demo
), which is an associative array. We have defined a type
key as a normal menu item. Thus we will see a link to our page in the main navigation block. The title
is the link title. If we do not set a page title, this will also be the page title. Access to the menu is controlled by the access arguments
key, and, in this case, all roles with the "access content" permission are granted access to this menu item.
The value of the page callback
key is the name of the function where the page is built and returned. The function should return a string, HTML, or any output that the caller can understand and present to the end user. It may be as simple as this:
/**
* Build page output.
*
* @return string
*/
function simple_page_demo_output() {
drupal_set_title("Simple page title");
return "This is a simple page";
}
When an HTTP request for /simple-page-demo
is received in index.php
, the menu_execute_active_handler()
function is called. That is where the /simple-page-demo
path is matched to the correct menu item and the page callback function is executed.
Ideally, this function should return a renderable array, but an HTML string is also acceptable. If there is no content, NULL may be returned. Alternatively, an integer representing a defined menu status constant or status code (e.g. MENU_NOT_FOUND
, MENU_ACCESS_DENIED
, MENU_SITE_OFFLINE
, etc.) may be returned too. By the way, having a menu status code as the output is not ideal, because you may return MENU_SITE_OFFLINE
while strictly speaking, the site is not offline at all.
For the purpose of our demonstration, the returned simple string is sufficient. Later, the Drupal 7 templating system takes over, and the page is displayed.
Drupal 8
In Drupal 8, our custom code lives in a module too. Paths are defined in a YAML routing configuration file. Again, assuming we have a simple_page_demo
module, this will be our simple_page_demo.routing.yml
file:
# simple_page_demo.routing.yml
simple_page_demo.page:
path: '/simple-page-demo'
defaults:
_title: 'Simple page title'
_controller: '\Drupal\simple_page_demo\Controller\SimplePageController::page'
requirements:
_access: 'TRUE'
The id
of this route is simple_page_demo.page
and it should be unique. _title
is the page title. We specify where the page content will come from in the value of the _controller
key. The controller class needs to be created with the implementation of page()
method. Here, we return a renderable array:
<?php
namespace Drupal\simple_page_demo\Controller;
class SimplePageDemoController {
/**
* Build page output.
*
* @return array
*/
public function page() {
return array(
'#markup' => "This is a simple page",
);
}
}
The page title may also be dynamic, but the route requires a _title_callback
key instead of _title
. If our YAML example looks like this:
# simple_page_demo.routing.yml
simple_page_demo.page:
path: '/simple-page-demo'
defaults:
_title_callback: '\Drupal\simple_page_demo\Controller\SimplePageDemoController::title'
_controller: '\Drupal\simple_page_demo\Controller\SimplePageDemoController::page'
requirements:
_access: 'TRUE'
Then our callback in the SimplePageDemoController
class may look like this:
// src\Drupal\simple_page_demo\Controller\SimplePageDemoController.php
public function title() {
return "Simple page title";
}
To display a link in the main navigation block, we create a simple_page_demo.links.menu.yml
configuration file:
# simple_page_demo.links.menu.yml
simple_page_demo.menu:
title: 'Simple page demo'
route_name: simple_page_demo.page
When the HTTP request for /simple-page-demo
is received in the index.php
file, the HttpKernel
converts the request into a Symfony Request
object and calls the handle()
method on it. The controller is resolved, loaded, and called. What is returned is a Response
object. Then, the Twig templating system kicks in, and the page is displayed.
Conclusion
This is a brief look at how to output a simple page in both Drupal 7 and 8. It is to illustrate what is required for transitioning to Drupal 8 development apart from understanding the Object-Oriented Programming principles on which it has been built. In addition, we have not looked at things like theming, templating or any of the more complex aspects of page rendering.
Code
Demo modules for this article are in the X-Team Drupal 7 Examples and Drupal 8 Examples Github repositories.