May 20, 2014

Initial cut at routing system with PSR-4 autoloading

According to some docs, Drupal 8 is currently in a transitional phase during which either of the autoloading standards PSR-0 or PSR-4 will work. Regardless, it seems definite that PSR-4 has been accepted and that modules should be implemented to it.

Much of my confusion about the two PSRs was due to not understanding that the difference between them only affects the directory structure and the location of files. Their differences do not affect the conventions for how namespaces are to be defined and used in the code.

Adding to my confusion is the fact that some articles were written to PSR-0, some to PSR-4, and some when it looked like there was going to be a transition from the former to the latter. It took some doing to sort through this.

Following PSR-4, I was able to implement a stripped down, demo use of the routing system.

First, there is the .routing.yml file.

(1)  modules/custom/optimizely/optimizely.routing.yml

(2)  The .routing.yml file replaces the routing functionality that was provided in D7 by implementing hook_menu(). The file contents for this demo are:
optimizely.settings:
  path: /admin/config/system/optimizely
  defaults:
    _content: \Drupal\optimizely\Controller\OptimizelyController::hello
    _title: hello
  requirements:
    _permission: 'view content'
Next, the PHP file that defines the class and its method that are referred to in the .routing.yml file. Each such code file should contain a single class definition. Note the file location.

(3)  modules/custom/optimizely/src/Controller/OptimizelyController.php

(4)  Class definition with its namespace.
namespace Drupal\optimizely\Controller;

class OptimizelyController {
  public static function hello() {
    return array(
      '#markup' => t('<em>Hello Optimizely!</em>'),
    );
  }
}
Notes:
  • The _content property in optimizely.routing.yml specifies a class method to be called to return a render array. The method may be either static or non-static.
  • The namespace Drupal\optimizely corresponds to the directory modules/custom/optimizely/src, where the custom subdirectory is something I added. The remainder of the namespace corresponds one-to-one to subdirectories in the obvious way. In this case, the \Controller portion of the namespace corresponds to the Controller subdirectory, which I added for organizing code files.
  • The #type key which has been documented for the render array is no longer used.
  • A valid D8 module is not required to have a  .module file.
  - - -

These two files together with optimizely.info.yml comprise a working D8 module that displays a "Hello Optimizely!" page when you browse to the path.

Update: see  http://optimizely-to-drupal-8.blogspot.com/2014/12/beta-3-beta-4-routes-use-controller.html


Sources:

Routing functionality of hook_menu() has been replaced by new routing system
https://drupal.org/node/1800686

PSR-4 namespaces and autoloading in Drupal 8
https://drupal.org/node/2156625
A few examples of how PHP namespaces are mapped to the directory structure.

PHP class autoloading changed to PSR-4 instead of PSR-0
https://drupal.org/node/2246699
This article clarified for me that the PSR change only affects file locations, not the PHP namespaces.

Routing system in Drupal 8
https://drupal.org/developing/api/8/routing
Several chapters / webpages on how to use the routing system. I found the first three chapters adequate as a start, as the subsequent ones are more advanced.

4 comments:

  1. What are your feelings about the differences between PSR-0 vs PSR-4? You mentioned the directory structure difference, is there anything else? What's the point of choosing one over the other and why did the project change half way through? I'm so thankful that autoloading will be supported. It felt like the stone ages without it.

    Can you explain more about the `#type` key? Is it still used or optional? Perhaps post an example or a source that supports your statement?

    ReplyDelete
    Replies
    1. As I understand it, PSR-4 requires a simpler and shallower directory structure. That was enough of an advantage that it was worth the pain of switching from one standard to the other.

      The use of namespaces in the code is not affected by this change.

      I'm in favor of the change. The deeper the filesystem structure, the harder it is to navigate it, even when you have supportive tools.

      It was confusing for me as a beginner to have various write-ups and tutorials, written at different points in time, that used one or the other or both and having to sort through it all. I had to glean what is current and accurate from what is now beoming obsolete.

      "Drupal and PSR-0/PSR-4 Class Loading"
      https://drupal.org/node/1971198

      Delete
    2. I only mentioned the #type key because it shows up in example code in tutorials, but it's no longer needed. Apparently, in the past #type was needed together with #markup .

      My own demo code only has #markup and works fine.

      Delete
    3. I want to emphasize that the #type key is optional if #markup is used. However, it looks required together with certain other keys. I will keep in mind the need to clarify this in future posts.

      Delete