CHAPTER 4

image

Creating a Basic Drupal Module with HTML Output

Now that you’ve gotten your feet wet with HTML, this chapter shows you how to use HTML to create your own custom web pages within the Drupal framework. In this chapter, I’m actually going to jump ahead a bit. Even though I’m going to assume you don’t know any PHP (a server-side scripting language designed for web development), I’m going to give you just enough right now so you can play around with showing basic HTML in a programmatically created Drupal page—that is, via a Drupal module.

In order to create your module, you first need to locate your Drupal docroot directory, which is where your Drupal files are housed. You’ll be placing your own files you create within the Drupal directory structure so that you can integrate your custom pages into your Drupal site.

Working with the Drupal Docroot Directory

So what is a docroot directory? Well, to begin, you need to know that there are two docroot directories: an Apache docroot and a Drupal docroot. Let’s look at the Apache docroot directory first.

The Apache docroot is the location from which your local Apache web server will serve up web pages—any web pages, not just your Drupal installation. Often the name of the folder for the Apache docroot directory will be htdocs or the /var/www/ directory, which is the most commonplace on an Ubuntu server (the location of the docroot directory can also be configured to be in any other directory, but usually it is in the default location at /var/www).

Your Drupal docroot directory is the base, or “home,” directory of your Drupal installation and it’s where all your Drupal files and folders reside. You can really put the Drupal docroot anywhere within the Apache docroot directory. If you use Acquia Dev Desktop out of the box on a Mac, the Drupal docroot directory will just be within your Sites/devdesktop directory, which is within your user’s home directory. On my Mac, mine is at, for example, /Users/jbarnett/Sites/devdesktop. On a Windows machine, the Drupal docroot directory is most often at C:/Users/your_username/Sites. Acquia Dev Desktop for Windows, puts the Drupal docroot within C:/Users/your_username/Sites/devdesktop. Within this devdesktop directory you’ll find all the site folders for each Drupal installation you’ve created using Acquia Dev Desktop.

When you need to configure where your Drupal docroot is or you want to create another instance of Drupal on your local machine or on an Ubuntu server in the cloud (at Amazon, Rackspace, Linode, or any other server farm in the cloud), you will set up an Apache virtual host (something I won’t get into now). Fortunately, Acquia Dev Desktop already sets this up for you, which allows you to proceed more quickly. An Apache virtual host is configured to “wire” it so your web server at a particular web URL serves up the correct files within your Apache docroot—whether they be Drupal files, HTML files, straight up PHP files, and so on.

Now that you know where your Drupal files are stored you can begin creating your first Drupal module.

Creating a Basic Drupal Module

In this section, we are going to create a basic Drupal module. Recall that a module is like a plug-in that extends Drupal’s functionality. In this case, the module you create will be used to create a simple web page that looks like the one shown in Figure 4-1. Simply, this module will output the following HTML to the screen (as shown in Figure 4-1):

<p><b>Saying Hello World in Drupal 8 is cool!</b></p>

9781430264668_Fig04-01.jpg

Figure 4-1. A bare bones custom-created Drupal module showing some basic HTML

Image Note  The code for this Drupal module is on Github: https://github.com/barnettech/drupal8_book.

Within a subfolder of your Drupal docroot directory (likely under /Users/your_username/Sites/devdesktop on a Mac or within C:/Users/your_username/Sites on a Windows machine), you’ll see a file list that looks as follows:

README.txt          example.gitignore      robots.txt
composer.json       index.php              sites
composer.lock       modules                themes
core                profiles               web.config

You can navigate to your Drupal docroot folder within the file browser that comes with your Mac or with Windows, or you can use the command line if you’re comfortable with that.

  1. To begin, locate the modules folder. On my Mac it looks as follows: /Users/jbarnett/Sites/devdesktop/drupal-8.0.0-beta6/drupal/modules.

    Image Note  The Drupal 8 directory structure is different from previous versions of Drupal. In Drupal 7 and prior, the modules directory in Drupal’s docroot directory contained core modules (modules that come with Drupal) only, and the contrib (community contributed) and custom modules used to live in the sites/all/modules directory. The Drupal community thought this was confusing and wanted something more intuitive. Now when a developer sees the Drupal docroot directory, and within it the modules directory, he or she can think, “Oh, that is where my modules I develop or download should go.” Drupal core modules now live within the core/modules directory.

  2. Within this modules directory, create two folders, if they don’t exist already: a contrib folder and a custom folder. In the contrib directory, you’ll be putting all the community-contributed modules that you download from drupal.org (or elsewhere), and in the custom directory you’ll be putting any modules that you create from scratch. This is the standard convention used in the Drupal community for organizing your modules.
  3. Within the custom folder that you just created, create a folder called hello_world, which will also serve as the name of your new custom module.
  4. Create three files within this subdirectory (using your code editor or the Linux command line). First, create a file called hello_world.info.yml and then create a file called hello_world.module. Naming the files with the same name as the module name is essential. Finally, create a file named hello_world.routing.yml.

    Image Note  The code for this Drupal module is on Github: https://github.com/barnettech/drupal8_book. The code will be formatted better at Github compared to reading it on your Kindle device/e-reader because it includes syntax highlighting.

  5. The first file we’re going to create is the hello_world.info.yml file, and this file is a basic file that tells the Drupal system there is a new module and to look for the appropriate files and functions within it. Without this file, your module will not be recognized. Type the following into the hello_world.info.yml file:
    name:  Hello World
    type:  module
    description:  'A basic Drupal 8 Hello World Module.'
    package:  Custom Modules
    version:  1.0
    core:  8.x

    The file hello_world.info.yml has a .yml extension and is a YAML file. YAML files are used to store metadata about all themes and modules, something that was done in .info files prior to Drupal 8.

    Image Note  For users who’ve used Drupal 7 and previous versions, you may wonder why Drupal switched in Drupal 8 to using YAML rather than continuing to use just an .info file with standard text file format. I found this answer: “Why YAML, that’s also by exclusion. First, we are looking for a file format that is both human editable and computer parsable. We did not want a Drupal-specific format (info files). We did not want XML because then the schema is the Drupalism (and XML has cooties). JSON (JavaScript Object Notation) doesn’t allow comments and non-ASCII characters need escaping, that’s not nice for humans. So, YAML.” (Excerpt by NK at www.drupal4hu.com/node/377.)

  6. The next bit of code wires the Drupal system to register the new hello/world URL and connects (routes) that URL to the code located in the HelloWorldController and specifically to the code in the method (a grouping of code) myCallbackMethod. This code also sets the permissions to be only for those with the right to “access content.” Type the following code into the hello_world.routing.yml file:
    hello_world_settings:
      path:  '/hello/world'
      defaults:
        _controller:  'Drupalhello_worldControllerHelloWorldController::
    myCallbackMethod'
        _title: 'Hello World'
      requirements:
        _permission: 'access content'
  7. Now we need to make a few more directories and one more file, and we’ll be done. Make sure you’re within the hello_world module directory and then create a directory called src. Within the src directory, create a folder called Controller. The directory structure should look like this: hello_world/src/Controller.

    Image Note  This directory structure is very different from Drupal 7 and prior versions; we never needed to create this kind of directory structure previously, but with the new object-oriented way of doing things, it is now necessary. If the directory structure is at all confusing, look at the code in Github—you’ll be able to see the directory structure. You can also download (“clone”) the project from Github, which will bring the files and directory structure down to your own computer.

  8. The next file, as stated earlier, houses the myCallbackMethod, which gets invoked in the hello_world.routing.yml you just set up. That method will house the HTML code that will display within the new web page you’re creating at the hello/world URL.

    Image Note  A method in object-oriented coding is very similar to a function in the procedural (non-object-oriented) code you may be more familiar with. It is a block of code that is grouped together for easier invocation. The hello_world.routing.yml file (specifically, the line following _controller: invokes this myCallbackMethod) you created earlier is the file that invokes this myCallbackMethod so its code will get executed.

  9. Within this new hello_world/src/Controller directory, create the file HelloWorldController.php and type the following code in this file:
    <?php
    /**
     * @file
     * Contains Drupalhello_worldHelloWorldController.
     */

    namespace Drupalhello_worldController;
    /**
     * Provides route responses for the hello world page example.
     */
    class HelloWorldController {
      /**
       * Returns a simple hello world page.
       *
       * @return array
       *   A very simple renderable array is returned.
       */
      public function myCallbackMethod() {
        $element = array(
          '#markup' => '<p><b>Saying Hello World in Drupal 8 is
    cool!</b></p>',
        );
        return $element;
      }
    }
  10. Notice the following line which is the specific line that houses all the HTML code that will display to the user on the new web page:
    $content = '<p><b>Saying Hello World in Drupal 8 is
    cool!</b></p>';

    Image Note  The code you’ve seen so far is the amount of coding it takes to put some basic HTML on a page in Drupal 8. The boilerplate code is a bit more complex than in previous versions of Drupal, as Drupal 8 incorporates the Symphony routing system. Drupal 8 has taken on new, more “modern” architecture from the Symphony PHP framework (http://symfony.com/), and Drupal 8 leaps to try to adopt more modern architectural paradigms, which Symphony already handles well. This leap for the Drupal community brings Drupal more up to date with other object-oriented frameworks. Don’t worry for now if you don’t understand every line of PHP code presented.

  11. Locate the admin toolbar, click the Manage tab, and then click Extend (or in your browser, go to the ...admin/modules URL). Enable your new module by clicking the check box next to “Hello World” and then click the “Save configuration” button. See Figure 4-2 as an example of what your new module should look like on the module management page.

    9781430264668_Fig04-02.jpg

    Figure 4-2. Enabling your new custom module, which outputs some HTML to the screen

  12. In your browser open your Drupal site to: http://localhost/hello/world. Be sure to replace localhost with whatever the URL is for your Drupal site. (On my computer, it’s http://drupal8:8888/hello/world.)

You’ll now see your simple Drupal page in all its glory, showing some basic HTML on the page (see Figure 4-3). Your screen may look different if you’ve installed a different Drupal theme.

9781430264668_Fig04-03.jpg

Figure 4-3. The module outputted the basic HTML into the center of the Drupal page

Now when I introduce you to CSS, PHP, JavaScript, and so on later in the book, I can show you the featured technology as used outside Drupal, and also within a Drupal module, within the Drupal framework. We’ll be adding to this Drupal module to showcase each new technology. The example code you just looked at is pretty simple, only displaying some HTML on the screen, but this code is the framework you’ll add to in order to create more complex web pages.

If any of the code presented just now is confusing, don’t worry too much. For now just imagine this code as a bunch of magic and put your HTML within the quotes within the line $content = '<p><b>Saying Hello World in Drupal 8 is cool!</b></p>', and that HTML will be the output on the web page.

Looking at the Model, View, Controller Design Pattern

To get into the wisdom behind the architecture you’re seeing in Drupal 8, it’s necessary to talk about the controller you just saw in the Hello World module (the HelloWorldController.php file you just created). The controller is the “C” in the Model, View, Controller (MVC) architecture, which is popular in almost all coding languages, and it separates “concerns,” separating the view code, logic, and data. By separating these different pieces of architecture, the code is more organized, and it helps in keeping “themers” in the “view” and developers on the back end, which means themers and developers should experience less collision when working together.

Image Note  You can read more about controllers at https://drupal.org/project/controller.

The system separates the view (the theming/presentation layer) from the back-end data (the model), and the logic/strategy (in the controller) of responding to the user’s actions they initiate in the view. For example, the view—the look and feel of the site—can be replaced or heavily modified, and the core data and logic behind the view can be unaffected by the change. This system also allows you to have multiple views of the back-end data (the model) and allows a change to the model to affect all views of the data—the key idea of the “observer pattern” in software architecture. You can read more about MVC in the book Design Patterns by Richard Helm, Ralph Johnson, John M. Vlissides, and Craig Larman (often referred to as “The Gang of Four”) (Addison-Wesley, 1994).

Showcasing Different HTML Elements Within the Drupal Module

Most HTML elements you saw in Chapter 3, like tables and lists, can be easily put into your new Drupal module’s output. The exception is forms, which are more complicated and will be covered in Chapter 14.

Image Note  When you put HTML into your Drupal module you omit the <html>, <head>, and <body> tags. Drupal puts these tags in for you.

Take, for example, the code to create anchors (see Chapter 3). You can easily put this code into the new Drupal module in the HelloWorldController.php controller file. The new file will now look as follows:

<?php
     /**
      * @file
      * Contains Drupalhello_worldHelloWorldController.
      */

     namespace Drupalhello_worldController;

     /**
     * Provides route responses for the hello world page example.
      */
     class HelloWorldController {
       /**
        * Returns a simple hello world page.
        *
        * @return array
        *   A very simple renderable array is returned.
        */
       public function myCallbackMethod() {
         $content = '
     <a id="top"></a>
         <h2>
           <p><a href="#section1">Visit Section 1</a></p>
           <p><a href="#section2">Visit Section 2</a></p>
           <p><a href="#section3">Visit Section 3</a></p>
           <p><a href="#section4">Visit Section 4</a></p>
           <p><a href="#section5">Visit Section 5</a></p>
         </h2>

         <p><h2><a id="section1">Section 1</a></h2><p>
         <p>
           Veggies sunt bona vobis, proinde vos postulo esse magis
     tigernut wakame jícama spring onion tatsoi zucchini yarrow.
           Komatsuna amaranth catsear celery quandong zucchini chickweed
     chard coriander spring onion winter purslane turnip greens swiss chard
     radicchio bok choy mustard squash. Rock melon carrot tomatillo cabbage
     rock melon leek courgette. Chickweed beetroot tigernut epazote bitterleaf
     courgette dandelion bell pepper earthnut pea salsify radicchio soko sea
     lettuce okra pumpkin. Veggies sunt bona vobis, proinde vos postulo esse
     magis tigernut wakame jícama spring onion tatsoi zucchini yarrow.

... text ommitted here to save space ...

       </p>

       <p><h2><a href="#top">Take me back to the top!</a></h2></p>

         <h2><a id="section2">Section 2</a></h2>
         <p>

           Peanut mustard chickweed lotus root yarrow summer purslane desert
     raisin endive corn green bean rutabaga pumpkin lettuce. Arugula zucchini
     courgette leek bunya nuts eggplant water spinach tatsoi yarrow potato rock
     melon kohlrabi jícama bell pepper shallot burdock. Pumpkin chicory caulie
     tigernut courgette celery. Tigernut salad cress komatsuna earthnut pea
     cauliflower bell pepper spring onion cucumber. Kale taro cress broccoli
     beetroot corn salsify water spinach chickpea beet greens cucumber dandelion
     arugula prairie turnip caulie cauliflower.  Peanut mustard chickweed lotus
     root yarrow summer purslane desert raisin endive corn green bean rutabaga
     pumpkin lettuce. Arugula zucchini courgette leek bunya nuts eggplant
     water spinach tatsoi yarrow potato rock melon kohlrabi jícama bell pepper
     shallot burdock. Pumpkin chicory caulie tigernut courgette celery. Tigernut
     salad cress komatsuna earthnut pea cauliflower bell pepper spring onion
     cucumber. Kale taro cress broccoli beetroot corn salsify water spinach
     chickpea beet greens cucumber dandelion arugula prairie turnip caulie
     cauliflower.

... text ommitted here to save space ...

         </p>
       <p><h2><a href="#top">Take me back to the top!</a></h2></p>

         <h2><a id="section4">Section 4</a></h2>
         <p>
           Artichoke arugula collard greens kale tomato scallion catsear
     celery turnip bunya nuts endive seakale wattle seed nori daikon fava bean
     parsnip. Burdock zucchini caulie garlic rock melon pumpkin. Eggplant
     endive kombu asparagus tomatillo artichoke. Artichoke arugula collard
     greens kale tomato scallion catsear celery turnip bunya nuts endive
     seakale wattle seed nori daikon fava bean parsnip. Burdock zucchini caulie
     garlic rock melon pumpkin. Eggplant endive kombu asparagus tomatillo
     artichoke.

... text ommitted here to save space ...

         <h2><a id="section5">Section 5</a></h2>
         <p>
           Artichoke parsley ricebean desert raisin caulie grape kakadu plum
     collard greens leek courgette seakale mustard nori sorrel amaranth
     courgette peanut beetroot. Maize corn beet greens lettuce broccoli parsnip
     garlic chickweed groundnut garbanzo brussels sprout kombu rock melon bamboo
     shoot seakale endive cauliflower. Celery cucumber coriander cress desert
     raisin silver beet pumpkin quandong cauliflower kombu garlic squash.
     Artichoke parsley ricebean desert raisin caulie grape kakadu plum collard
     greens leek courgette seakale mustard nori sorrel amaranth courgette peanut
     beetroot. Maize corn beet greens lettuce broccoli parsnip garlic chickweed
     groundnut garbanzo brussels sprout kombu rock melon bamboo shoot seakale
     endive cauliflower. Celery cucumber coriander cress desert raisin silver
     beet pumpkin quandong cauliflower kombu garlic squash.

... text ommitted here to save space ...

        </p>
        <p><h2><a href="#top">Take me back to the top!</a></h2></p>
        ';
         $element = array(
           '#markup' => $content,
         );
         return $element;
       }

Notice the code ported over from the HTML from Chapter 3; we only needed to omit the <html>, <head>, and <body> tags. Figure 4-4 shows what the anchor code from Chapter 3 looks like in the Drupal module.

9781430264668_Fig04-04.jpg

Figure 4-4. HTML anchors in a simple Drupal module

Now, for example, if you click “Visit Section 5” at the top of the screen, you are sent to Section 5, which is much farther down the page (see Figure 4-5). The anchor HTML code works just as expected within the HelloWorldController.php file.

9781430264668_Fig04-05.jpg

Figure 4-5. The anchor at Section 5

Image Note  In Chapter 12, you’ll learn a better way to handle HTML output—by creating theme functions—to further separate the view of the web page from the controller logic.

If you want to put a basic HTML table into the HelloWorldController.php file, it would look as follows:

<?php
     /**
     * @file
      * Contains Drupalhello_worldHelloWorldController.
      */

     namespace Drupalhello_worldController;

     /**
     * Provides route responses for the hello world page example.
      */
     class HelloWorldController {
       /**
        * Returns a simple hello world page.
        *
        * @return array
        *   A very simple renderable array is returned.
        */
       public function myCallbackMethod() {
         $content = '
     <table border="1">
       <tr>
         <th>Header 1</th>
         <th>Header 2</th>
       </tr>
       <tr>
         <td>row 1, cell 1</td>
         <td>row 1, cell 2</td>
       </tr>
       <tr>
         <td>row 2, cell 1</td>
         <td>row 2, cell 2</td>
       </tr>
     </table>
           ';
         $element = array(
           '#markup' => $content,
         );
         return $element;
       }

Again, you omit the <body>, <html>, and <head> tags. Figure 4-6 shows what the Drupal page looks like at the ...hello/world URL.

9781430264668_Fig04-06.jpg

Figure 4-6. The Basic Drupal module with HTML in it to create a table

And finally, here is our HelloWorldController.php file with HTML code to create both unordered lists and ordered lists.

<?php
     /**
      @file
      * Contains Drupalhello_worldHelloWorldController.
      */
     namespace Drupalhello_worldController;
     /**
     Provides route responses for the hello world page example.
      */
     class HelloWorldController {
       /**
        * Returns a simple hello world page.
        *
        * @return array
        *   A very simple renderable array is returned.
        */
       public function myCallbackMethod() {
         $content = '
     ORDERED LIST:
     <ol>
       <li>Item 1</li>
       <li>Item 2</li>
     </ol>
     UNORDERED LIST:
     <ul>
       <li>Item 1</li>
       <li>Item 2</li>
     </ul>
        ';
         $element = array(
           '#markup' => $content,
         );
         return $element;

See Figure 4-7 for an example of what the Drupal page looks like with the HTML creating both ordered and unordered lists.

9781430264668_Fig04-07.jpg

Figure 4-7. Our simple Drupal module with HTML output creating first an ordered list and then an unordered list

Renaming a Module—and How to Create a Module Not Named “hello_world”

If you would like to change the name of your module, you must change all the filenames and function names in the module. You also must change the folder name that houses the module’s files. So In the case of the example module, the folder name was hello_world. So if you wanted to change the module name to my_module, you would need to change the folder name to my_module. Then, within the my_module folder, you would need to change the hello_world.info.yml file to my_module.info.yml instead. Also the hello_world.module file would be renamed to be my_module.module. Then within the my_module.info.yml file, you would change the name of the module if you wish to. Then within the my_module.module file, you would change all the function names to begin with my_module rather than hello_world. So if you have functions called hello_world_cron (to have Drupal run new cron tasks; cron tasks refer to tasks to be run on a schedule) and hello_world_permission (to create new Drupal permissions) which implement the hook_cron and hook_permission Drupal hooks respectively, you would change these function names to my_module_cron and my_module_permission.

Image Note  Hooks are bits of code that allow you to alter or add to Drupal functionality. It’s important to preface all your hooks with your module’s name; otherwise, they will not run.

Drupal looks for any hook declarations that are in your Drupal installation, and runs the code at the appropriate time based on what type of hook it is. hook_cron is a hook in the Drupal system that has Drupal run the code within the hook_cron function on a schedule. hook_permission is a Drupal hook which allows you to define new Drupal permissions.

If you create a new module from scratch, the same conventions apply: The folder name must match the prefix of your function names, and the filenames must contain the name of your module.

Summary

In this chapter you took the HTML skills you acquired in Chapter 3 and learned to output HTML in a Drupal module. You learned the basic structure of a Drupal module and about the different pieces needed to create a module that included a controller and some YAML configuration files. We learned that the directory structure and how we name our files matter to wire up a Drupal module to work. Finally, you took a first look at how hooks work in Drupal to alter and add to Drupal.

As you learn about PHP later in the book, the boilerplate code used to create a module will make more sense to you. For a beginning Drupaler, copying and pasting boilerplate code and editing the code to do what you need it to do can take you a long way toward being a successful Drupal programmer. To fully understand the new code needed to create a Drupal hello world module, you would need to study object-oriented PHP programming. My favorite book on the subject is PHP 5 Objects, Patterns, and Practice by Matt Zandstra (Apress, 2005) (see www.apress.com/9781590593806). This chapter fearlessly showed you how to create a Drupal module without assuming you had read a book on object-oriented programming. Know that a primary paradigm in object- oriented programming is to create a bit of code (a class) that can be extended easily by other programmers to accomplish a task. In fact, the whole point is to abstract the coding behind the scenes, so other programmers can build upon what has already been done, not needing to concern themselves necessarily with what has already been built.

Abstraction is key to all engineering. We can program in a programming language because other engineers have already created a computer for us. All we need to do is write Drupal code. I don’t concern myself (often) with how the computer I’m using was made. This is abstraction, and in my mind is the basic idea behind the quote, “We stand on the backs of giants.” So don’t be overly concerned if the boilerplate code in creating a Drupal module is a bit of a black box. You now have learned the basic skills of creating a Drupal module, which is a highly valuable skill by itself.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset