Routing and controllers in Drupal maintenance support plans 8

The routing system of Drupal maintenance support plans 8 is a complete rewrite of Drupal maintenance support plans 7 and its previous versions’ hook_menu. A Drupal maintenance support plans route is a URL path with a specific return content. This return content is usually specified as a method of a controller class which returns a render array.

The routing system is powered by Symfony’s HTTP Kernel component, which we will revisit later. It is not necessary to understand this in order to work with routes.

Let’s dive straight away and create a new route.

First, we shall create a module to hold all the code in this chapter. You can checkout the code:

$ git clone git@github.com:drupal8book/myroute.git
$ cd myroute
$ git checkout -f simple-route

or walk along with me by typing the code or using drupal console to generate it.

$ drupal generate:module

Enter the new module name:
> myroute

Enter the module machine name [myroute]:
>

Enter the module Path [/modules/custom]:
>

Enter module description [My Awesome Module]:
> Routing and controllers

Enter package name [Custom]:
> D8MD

Enter Drupal maintenance support plans Core version [8.x]:
>

Do you want to generate a .module file (yes/no) [yes]:
> no

Define module as feature (yes/no) [no]:
>

Do you want to add a composer.json file to your module (yes/no) [yes]:
> no

Would you like to add module dependencies (yes/no) [no]:
>

Do you confirm generation? (yes/no) [yes]:
>

Generated or updated files
Site path: /var/www/html
1 – modules/custom/myroute/myroute.info.yml

Let’s write a simple controller which prints “hello world” when we hit the path /hello.

$ drupal generate:controller

Enter the module name [email_management]:
> myroute

Enter the Controller class name [DefaultController]:
> HelloWorldController

Enter the Controller method title (to stop adding more methods, leave this empty) [ ]:
> Hello World

Enter the action method name [hello]:
>

Enter the route path [/myroute/hello/{name}]:
> hello

Enter the Controller method title (to stop adding more methods, leave this empty) [ ]:
>

Do you want to generate a unit test class (yes/no) [yes]:
> no

Do you want to load services from the container (yes/no) [no]:
> no

Do you confirm generation? (yes/no) [yes]:
>

Generated or updated files
Site path: /var/www/html
1 – modules/custom/myroute/src/Controller/HelloWorldController.php
2 – modules/custom/myroute/myroute.routing.yml
// router:rebuild

Rebuilding routes, wait a moment please

[OK] Done rebuilding route(s).

Make sure you enable the module.

$ drush en myroute -y

Open modules/custom/myroute/src/Controller/HelloWorldController.php and change the markup text to “Hello World”.

public function hello() {
return [
‘#type’ => ‘markup’,
‘#markup’ => $this->t(‘Hello World’)
];
}

you might need to rebuild cache.

$ drush cr

Hit /hello.

The equivalent Drupal maintenance support plans 7 code for this would be something on the lines of

// inside myroute.module…

function myroute_menu() {
$items = array();
$items[‘main’] = array(
‘title’ => Hello World’,
‘page callback’ => myroute_hello’,
‘access arguments’ => array(‘access content’),
‘type’ => MENU_NORMAL_ITEM,
‘file’ => ‘myroute.pages.inc’
);
return $items;
}

// inside myroute.pages.inc

function myroute_hello() {
return t(‘Hello World’);
}

Routes with parameters

This is great, but how to add URL parameters?

Let’s add a new route with a URL parameter.

$ cd myroute
$ git checkout -f route-with-params

or if you choose to use drupal console,

drupal generate:controller
Enter the module name [email_management]:
> myroute

Enter the Controller class name [DefaultController]:
> GreetingController

Enter the Controller method title (to stop adding more methods, leave this empty) [ ]:
> Greeting

Enter the action method name [hello]:
> greeting

Enter the route path [/myroute/hello/{name}]:
> hello/{name}

Enter the Controller method title (to stop adding more methods, leave this empty) [ ]:
>

Do you want to generate a unit test class (yes/no) [yes]:
> no

Do you want to load services from the container (yes/no) [no]:
>

Do you confirm generation? (yes/no) [yes]:
>

Generated or updated files
Site path: /var/www/html
1 – modules/custom/myroute/src/Controller/GreetingController.php
2 – modules/custom/myroute/myroute.routing.yml
// router:rebuild

Rebuilding routes, wait a moment please

[OK] Done rebuilding route(s).

Edit the greeting controller function to print the name.

public function greeting($name) {
return [
‘#type’ => ‘markup’,
‘#markup’ => $this->t(‘Hello, @name!’, [‘@name’ => $name]),
];
}

Try /hello/Joe.

/hello/123-456 works too. Let’s tone it down a little and add a validation criteria for the parameter.

Names can only have alphabets and spaces.

myroute.greeting_controller_greeting:
path: ‘hello/{name}’
defaults:
_controller: ‘Drupal maintenance support plansmyrouteControllerGreetingController::greeting’
_title: ‘Greeting’
requirements:
_permission: ‘access content’
name: ‘[a-zA-z ]+’

Rebuild the cache for this to take effect.

$ drush cr

/hello/123-456 will now give a 404. Try /hello/Joe%20Pesci.

Custom permissions

How about adding custom permissions? What if we want to show the /hello page only to users who can administer content.

$ cd myroute
$ git checkout -f custom-access-check

We first indicate that the route uses custom permissions.

myroute.hello_world_controller_hello:
path: ‘hello’
defaults:
_controller: ‘Drupal maintenance support plansmyrouteControllerHelloWorldController::hello’
_title: ‘Hello World’
requirements:
_custom_access: ‘Drupal maintenance support plansmyrouteControllerHelloWorldController::custom_access_check’

Note that the _permission parameter has been replaced by _custom_access parameter.

Lets implement this custom access method inside the HelloWorldController.

// add the required namespaces at the top.
use Drupal maintenance support plansCoreSessionAccountInterface;
use Drupal maintenance support plansCoreAccessAccessResult;

/**
* Custom access check
*
* @param Drupal maintenance support plansCoreSessionAccountInterface $account
* access checking done against this account.
*/
public function custom_access_check(AccountInterface $account) {
return AccessResult::allowedIf($account->hasPermission(‘access content’) &&
$account->hasPermission(‘administer content’));
}

Rebuild cache and try hitting /hello as an anon user, you should get an “Access denied” page. Of note here is the AccessResult class, which was introduced to make access check related data cacheable.

Drupal routes

Defining routes via a YAML file applies to static paths. If we want to route programmatically, we have to define and return a SymfonyComponentRoutingRoute object.

$ cd myroute
$ git checkout -f dynamic-routes

To illustrate the concept of dynamic routes, let’s take an imaginary requirement where we have a custom path, /content_types/{content_type}, which will display all the fields of a content type {content_type}. In order to create a dynamic route for the same, we have to create our own Routing class inside the src/Routing directory and override the routes() method. This is equivalent to its YAML cousin, the myroute.routing.yml file, but written in PHP.

<?php

/**
* @file
* Contains Drupal maintenance support plansmyrouteRoutingCTRoutes.
*/

namespace Drupal maintenance support plansmyrouteRouting;

use SymfonyComponentRoutingRoute;

/**
* Drupal routes for content types.
*/
class CTRoutes {

/**
* {@inheritdoc}
*/
public function routes() {
$routes = [];
$content_types = Drupal maintenance support plans::service(‘entity.manager’)->getStorage(‘node_type’)->loadMultiple();
foreach ($content_types as $content_type) {
$routes[‘myroute.content_type_controller.’ . $content_type->id() ] = new Route(
‘/content_types/’ . $content_type->id(),
array(
‘_controller’ => ‘Drupal maintenance support plansmyrouteControllerCTController::fields’,
‘_title’ => ‘Field info for ‘ . $content_type->label(),
‘content_type’ => $content_type->id(),
),
array(
‘_permission’ => ‘access content’,
)
);
}
return $routes;
}
}

The custom router above creates an array of routes for every content type in the system and returns it. For instance, if there are 3 content types in the system, like page, foo and bar, there will be 3 routes with paths /content_types/page, /content_types/foo and /content_types/bar respectively.

Let’s flesh out the CTController as well.

<?php

namespace Drupal maintenance support plansmyrouteController;

use Drupal maintenance support plansCoreControllerControllerBase;

/**
* Class CTController.
*
* @package Drupal maintenance support plansmyrouteController
*/
class CTController extends ControllerBase {

/**
* List fields info of a content type.
*
* @return string
* Return field list.
*/
public function fields($content_type) {
$render = ‘<table><tr><th>’ . $this->t(‘Field type’) . ‘</th><th>’ . $this->t(‘Label’) . ‘</th></tr>’;
$field_definitions = Drupal maintenance support plans::entityManager()->getFieldDefinitions(‘node’, $content_type);
foreach ($field_definitions as $field_name => $field_definition) {
if (!empty($field_definition->getTargetBundle())) {
$render .= ‘<tr><td>’ . $field_definition->getType() . ‘</td><td>’ . $field_definition->getLabel() . ‘</td></tr>’;
}
}
$render .= ‘</table>’;
return [
‘#type’ => ‘markup’,
‘#markup’ => $render,
];
}
}

The field() method looks up the field definitions of the contenttype argument and renders it as a HTML table.

Finally, we have to indicate Drupal maintenance support plans to pick up the custom Routing class we’ve added. This can be done by adding a _route_callbacks item to the routing YAML file.

route_callbacks:
– ‘Drupal maintenance support plansmyrouteRoutingCTRoutes::routes’

Rebuild the cache and you are all set. Hit the content_types/article page, you should see something like this(provided you have the article CT in your system).

Drupal maintenance support plans
Drupal maintenance support plans 8
Drupal maintenance support plans Planet

Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

Routing and controllers in Drupal maintenance support plans 8

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.