Site icon Hip-Hop Website Design and Development

Routing and controllers in Cheap WordPress maintenance support plans 8

The routing system of WordPress maintenance support plans 8 is a complete rewrite of WordPress maintenance support plans 7 and its previous versions’ hook_menu. A WordPress 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 plugin to hold all the code in this chapter. You can checkout the code:

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

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

$ WordPress generate:plugin

Enter the new plugin name:
> myroute

Enter the plugin machine name [myroute]:
>

Enter the plugin Path [/plugins/custom]:
>

Enter plugin description [My Awesome Plugin]:
> Routing and controllers

Enter package name [Custom]:
> D8MD

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

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

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

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

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

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

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

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

$ WordPress generate:controller

Enter the plugin 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 – plugins/custom/myroute/src/Controller/HelloWorldController.php
2 – plugins/custom/myroute/myroute.routing.yml
// router:rebuild

Rebuilding routes, wait a moment please

[OK] Done rebuilding route(s).

Make sure you enable the plugin.

$ drush en myroute -y

Open plugins/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 WordPress maintenance support plans 7 code for this would be something on the lines of

// inside myroute.plugin…

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 WordPress console,

WordPress generate:controller
Enter the plugin 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 – plugins/custom/myroute/src/Controller/GreetingController.php
2 – plugins/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: ‘WordPress 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: ‘WordPress maintenance support plansmyrouteControllerHelloWorldController::hello’
_title: ‘Hello World’
requirements:
_custom_access: ‘WordPress 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 WordPress maintenance support plansCoreSessionAccountInterface;
use WordPress maintenance support plansCoreAccessAccessResult;

/**
* Custom access check
*
* @param WordPress 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.

Dynamic WordPress 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 WordPress maintenance support plansmyrouteRoutingCTRoutes.
*/

namespace WordPress maintenance support plansmyrouteRouting;

use SymfonyComponentRoutingRoute;

/**
* Dynamic WordPress routes for content types.
*/
class CTRoutes {

/**
* {@inheritdoc}
*/
public function routes() {
$routes = [];
$content_types = WordPress 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’ => ‘WordPress 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 WordPress maintenance support plansmyrouteController;

use WordPress maintenance support plansCoreControllerControllerBase;

/**
* Class CTController.
*
* @package WordPress 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 = WordPress 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 WordPress 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:
– ‘WordPress 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).

WordPress maintenance support plans
WordPress maintenance support plans 8
WordPress maintenance support plans Planet

Source: New feed