Compared to Drupal 7, there are few more steps involved in creating a custom module in Drupal 8. That's because Drupal 8 is using Symfony 2 components. Like Symfony, Drupal 8 code is object-oriented.
Related Blog Posts
- If you are looking to learn Drupal 8, check out this list of free Drupal 8 tutorials.
- If you are looking to up your Drupal module development skill, you should learn how to debug PHP code using xdebug. The easiest way to set it up using PHPStorm IDE. Here's a blog post on how to debug Drupal 8 using PHPStorm.
Here are the steps to create a custom module in Drupal 8:
Step 1: File Structure
In Drupal 8, we should keep the custom or contributed modules under modules folder in the root directory.
modules/contrib/ modules/custom/
Note: For multisite configuration, you have to follow the file structure as described below for using modules specifically for each site.
sites/your_site_name_1/modules/ sites/your_site_name_2/modules/
Create "example" directory under "modules/custom" directory.
Step 2: Create .info.yml file
In Drupal 8, .info file changes to .info.yml. Old .info files have been converted to YAML and the .info parser has been removed. The new parser is the Symfony YAML component. The new file extension is .info.yml. This applies to modules, themes, and profiles.
Here is our example.info.yml file created under "examples" directory we created in Step 1.
name: Drupal 8 custom module example type: module description: 'Example for Drupal 8 modules.' package: Custom version: 8.x core: 8.x
Step 3: Creating .routing.yml
First we have to write the path in .routing.yml file. In Drupal 8, we make heavy use of Symfony2 components to handle routing. This involves defining routes as configuration and handling the callback in a controller (the method of a Controller class). Here is our example.routing.yml file:
example.my_page: path: '/mypage/page' defaults: _controller: '\Drupal\example\Controller\ExampleController::myPage' _title: 'My first page in Drupal8' requirements: _permission: 'access content'
The first line is the route [example.my_page]. Route is a symfony component, which maps an HTTP request to a set of configuration variables. In drupal8 route is defined as a machine name in the form of module_name.route_name, here is example.my_page {'module_name = example', 'route_name = my_page'}
Under path, we specify the path we want this route to register. This is the URL to the route, with a leading forward slash.
Under defaults, we have two things: the default page title (_title) and the _controller which references a method on the ExampleController class.
Under requirements, we specify the permission the accessing user needs to have to be able to view the page.
For more details about routing file you should consult this documentation.
Step 4: Create Route Controller Class
We have to create our ModuleController.php according to the PSR-4 naming standard. Create a folder "modules/custom/example/src/Controller". In this folder, create a file named "ExampleController.php" with the following content:
<?php /** * @file * @author Rakesh James * Contains \Drupal\example\Controller\ExampleController. * Please place this file under your example(module_root_folder)/src/Controller/ */ namespace Drupal\example\Controller; /** * Provides route responses for the Example module. */ class ExampleController { /** * Returns a simple page. * * @return array * A simple renderable array. */ public function myPage() { $element = array( '#markup' => 'Hello world!', ); return $element; } } ?>
Controller is a PHP function you create that takes information from the HTTP request and constructs and returns an HTTP response.
The controller contains whatever arbitrary logic your application needs to render the content of a page.The controller from the matched route is executed and the code inside the controller creates and returns a Response object.
Such as going to /mypage/page now executes the ExampleController::myPage() controller and render a page that simply prints Hello world!.
Step 5: Creating .module and hook_menu()
In Drupal 8, hook_menu() is used to define only menu items, not to define page callback functions as in Drupal 7. If we have hook_menu(), we need to make sure that the route and path in example.module should match exactly with the route and path which written in example.routing.yml. In our case, $items['/mypage/page'] in example.module is should be the same path: '/mypage/page' in example.routing.yml. Similarly the route 'route' => 'example.my_page' in example.module should be the same example.my_page: in example.routing.yml
Here is the content of the "example.module" file:
<?php /** * @File * Example custom module for Drupal 8. * @author Rakesh James */ /** * Implementing hook_menu(). */ function example_menu() { // The paths given here need to match the ones in example.routing.yml exactly. $items['/mypage/page'] = array( 'title' => 'First page', 'description' => 'This is a example page.', // The name of the route from example.routing.yml 'route' => 'example.my_page', ); return $items; }
Conclusion
Finally when you enable the module and go to /mypage/page URL, you'll see "Hello world!" text printed from our module. As you can see, creating custom module in Drupal 8 is little lengthier than Drupal 7. But it's really interesting and gives more versatility for customization. It will definitely take Drupal to higher level in software world. Here is the git repo for the example module in case you want to play around with it.
Related Blog Posts
- If you are looking to learn Drupal 8, check out this list of free Drupal 8 tutorials.
- If you are looking to up your Drupal module development skill, you should learn how to debug PHP code using xdebug. The easiest way to set it up using PHPStorm IDE. Here's a blog post on how to debug Drupal 8 using PHPStorm.
Comments
hook_menu() is deprecated in Drupal 8
Hi,
Thanks for the example to create custom module in Drupal 8. I would like to let you know that "hook_menu()" is replaced by new systems for routing in Drupal 8.
Reference : https://www.drupal.org/node/1800686
Thanks,
Karthik Kumar
Thank You Karthik for the
Thank You Karthik for the information , When i am creating this module, hook_menu was to fully replaced like now.
So whoever reading this article can skip the Step:5 and go to the Path "/mypage/page" You can see your "Hello World" printed on the page.
I apologies for the late reply :)
_content should be _controller in routing.yml
Hey,
Thanks for this Hello World example. I want to correct one thing here, in routing.yml file _content is not working it should be _controller.
Thank you Siddharth for
Thanks
Was racking my mind trying to get it to work and finally came upon this blog showing _content needs to be _controller. Thanks!
Single Quotes missing
In .routing.yml file:
Typo
_permission: 'access content
Fix
_permission: 'access content'
Fixed
Why not generate the code using DrupalConsole
Very helpful article
Thanks for this writing! When young students ask me what and how to do with drupal I'm sending them to drupal blogs like yours!
Wonderfully explained article
Wonderfully explained article. Helped me get started with Drupal 8 coding in one go.
Getting Page Not found Error
Is the path '\Drupal\example\Controller\ExampleController::myPage', the directory structure ?
Because when running this complete module code as (localhost/drupal_8/mypage/page), I'm getting Page Not found Error . So, do I need to replace 'Drupal with drupal_8'
Accumulate?
So to generate a page is it standard practice to change:
'#markup' => 'Hello world!',
to:
'#markup' => $toPage,
Let $toPage accumlate the HTML needed to generate a page.
This is me experimenting with reading from a database.
http://pastebin.com/EX7AiTE9
It works. I didn't clean up the code... I just want to know if that is a correct standard.
Thanks
Jeff
Nice example
Learn lot.