Khanh Hoang - Kenn
Kenn is a user experience designer and front end developer who enjoys creating beautiful and usable web and mobile experiences.
With the impending Drupal 8 code freeze, developers will be scrambling to get their modules ready in time for the official release. Moving to a much more object-oriented approach using the Symfony framework will have a number of obvious advantages, but not without its drawbacks. As someone who is somewhat familiar with OOP, and has dabbled in both Symfony and Zend, I'm not afraid to admit that learning MVC and OOP concepts are HARD! Now more than ever it's going to be important for Drupalers to start learning about these things early in order to be ready.
This series of blog posts will be aimed at helping developers ramp up on Symfony in order to be ready for Drupal 8 module development. In part 1, we will learn how to setup a simple module with an admin screen using a Symfony controller.
The first thing you'll notice in Drupal 8 is the changes to the file structure. Everything is much more straight forward. Each of the folders in the root directory, core, modules, profiles, sites, and themes, houses its respective components. With that being said, you'll start by placing your module folder inside the root modules directory;
modules/foobar
The old method of using .info files to initialize your module is going away in Drupal 8 and will be replaced with Symfony YAML(.yml) files. Old .info files will now become .info.yml files, and will look slightly different.
Inside your module folder(modules/foobar), create an empty file called foobar.module and a file called foobar.info.yml with the following contents;
name: Foobar type: module description: 'This is a demo for creating Drupal 8 modules.' package: Custom version: 8.x-1.0 core: 8.x dependencies: - node - block hidden: false
A few things to note would be the syntax of course, but also the use of the hidden property. Hidden will allow you to show or hide the module on the main module listing page. See an example of a more elaborate .info.yml file.
Controllers are a fundamental component of the MVC architecture(ie: Model-view-controller).
Read more about the MVC methodology.
In this tutorial, we are going to use a very basic controller to output a very basic admin screen. You'll need to create the following file, modules/foobar/lib/Drupal/foobar/Controller/FoobarController.php, with the following code;
<?php namespace Drupal\foobar\Controller; use Drupal\Core\Controller\ControllerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; class FoobarController implements ControllerInterface { public static function create(ContainerInterface $container) { return new static($container->get('module_handler')); } /** * This will return the output of the foobar page. */ public function foobarPage() { return array( '#markup' => t('This is the demo foobar page.'), ); } }
It's important to follow the same folder structure otherwise Symfony not be able to find the file.
In order to route a URL to a controller, you'll need to create the file modules/foobar/foobar.routing.yml with the following code;
foobar: pattern: 'admin/foobar' defaults: _content: '\Drupal\foobar\Controller\FoobarController::foobarPage' requirements: _permission: 'access administration pages'
Note that the _content parameter pretty closely follows the file structure where you put your controller file. This however is NOT really the case. This has to do with the PHP namespace in which the controller was defined which also tells Symfony where to lazy-load the files from. Also, the pattern parameter is the URL path which will be used for the admin page. Read more about the new routing system.
One interesting feature of Drupal 8 is the decoupling of hook_menu from the controller routes(as seen in step 4). Although a lot of the old hook_menu functionality remains, registering controllers only makes that path usable. In order to place these items into a menu, you'll still need to use hook_menu.
Inside foobar.module file place the following code;
<?php /** * Implements hook_menu(). */ function foobar_menu() { // The paths given here need to match the ones in foobar.routing.yml exactly. $items['admin/foobar'] = array( 'title' => 'Foobar', 'description' => 'This is the demo foobar page.', // The name of the route from foobar.routing.yml 'route_name' => 'foobar', ); return $items; }
Upon enabling the Foobar module you should see the Foobar menu item appear in your admin menu.
You're probably asking yourself one really big question, "Why the hell would I go through all of these steps when I can just use the old hook_menu method?" This is a perfectly valid question. If you bypass Symfony, you won't reap any of the benefits that it brings to the table - which are numerous. Like I said, Symfony is hard so it's important to start learning early.
Stay tuned for part 2 in the series.