36,59 €
Learn to create and customize impressive Drupal 8 modules to extend your website's functionalities
Key Features
Book Description
Drupal 8 comes with a release cycle that allows for new functionality to be added at a much faster pace. However, this also means code deprecations and changing architecture that you need to stay on top of. This book updates the first edition and includes the new functionality introduced in versions up to, and including 8.7.
The book will first introduce you to the Drupal 8 architecture and its subsystems before diving into creating your first module with basic functionality. You will work with the Drupal logging and mailing systems, learn how to output data using the theme layer and work with menus and links programmatically. Then, you will learn how to work with different kinds of data storages, create custom entities, field types and leverage the Database API for lower level database queries.
You will further see how to introduce JavaScript into your module, work with the various file systems and ensure the code you write works on multilingual sites. Finally, you will learn how to programmatically work with Views, write automated tests for your functionality and also write secure code in general.
By the end, you will have learned how to develop your own custom module that can provide complex business solutions. And who knows, maybe you'll even contribute it back to the Drupal community.
Foreword by Dries Buytaert, founder of Drupal.
What you will learn
Who this book is for
The primary target of this book is Drupal developers who want to learn how to write modules and develop in Drupal 8. It is also intended for Drupal site builders and PHP developers who have basic Object Oriented Programming skills.
A little bit of Symfony experience is helpful but not mandatory.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 838
Veröffentlichungsjahr: 2019
Copyright © 2019 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Pavan RamchandaniAcquisition Editor:Karan GuptaContent Development Editor:Keagan CarneiroTechnical Editor: Surabhi KulkarniCopy Editor: Safis EditingProject Coordinator:Kinjal BariProofreader: Safis EditingIndexer:Manju ArasanGraphics:Alishon MendonsaProduction Coordinator:Jayalaxmi Raja
First published: October 2017 Second edition: March 2019
Production reference: 1260319
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78961-236-3
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
When I started the Drupal project eighteen years ago, I could never have imagined the impact that my software project would have. Today, Drupal powers a full two percent of websites online, and it has a devoted open source community of more than a million people from all walks of life around the world.
The Drupal community has changed the way websites are built. Drupal has promoted a modular software architecture since its origins and, as a community, we have created thousands of modules, all freely available from the drupal.org website. Each module alters and extends Drupal's core capabilities and adds new functionality to a Drupal site. It's a credit to the collective efforts of thousands of clever people working together over a period of many years, not only for their own interests, but also for the benefit of others.
Drupal's modular architecture allows you to build any website that you can dream of. The speed at which websites can be assembled using Drupal and Drupal modules is exceptional. Not a single proprietary content management system has the depth and breadth of Drupal. And if some functionality is missing, it can be built using Drupal's many foundational services and open APIs.
In his excellent book, Drupal 8 Module Development - Second Edition, Daniel explains how you can build modules for Drupal. Daniel is a respected voice in the Drupal community, with expertise in Drupal dating back to Drupal 6. He is known for his extensive writing on topics related to Drupal development, primarily on his website at webomelette.com.
If you're new to Drupal, I give you my warm welcome and invite you to not only write modules for your Drupal project, but also to become part of the Drupal community.
Dries Buytaert
Founder and Project Lead of Drupal
Co-founder and CTO of Acquia
Dries Buytaert is the original creator and project lead for the Drupal open source web publishing and collaboration platform. He is co-founder and chief technology officer of Acquia, a venture-backed software company that offers products and services for Drupal. A native of Belgium, Buytaert holds a PhD in computer science and engineering from Ghent University and a licentiate in computer science (MsC) from the University of Antwerp. In 2008, Buytaert was elected Young Global Leader at the World Economic Forum, and is an MIT TR 35 Young Innovator.
Daniel Sipos is a senior web developer specializing in Drupal. He's been working with Drupal sites since version 6, and started out, like many others, as a site builder. He's a self-taught programmer with many years' experience working professionally on complex Drupal 7 and 8 projects. In his spare time, he runs webomelette, a Drupal website where he writes technical articles, tips, and techniques related to Drupal development.
Jakub Mroz is a digital vision and strategy architect, founder of Passion Ventures Digital, and a certified Acquia and Amazon Expert. He built his first software at the age of 14 (in 1995). He has worked on digital projects for brands like MTV, Jaguar, Bentley, Calvin Klein, Swarovski, Johnson & Johnson, Nestle, Rio Tinto, Jisc, etc. He supports global charities like Great Ormond Street Hospital (GOSH) and World Animal Protection. He has worked with all popular PHP-based CMS systems and frameworks. Since 2011, he has been actively supporting Drupal projects and promoting Drupal as the most advanced open source content management system. He delivers solutions not only for enterprises and brands, but also for small and medium businesses.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Drupal 8 Module Development Second Edition
About Packt
Why subscribe?
Packt.com
Foreword
Contributors
About the author
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Get in touch
Reviews
Developing for Drupal 8
Introducing Drupal (for developers)
Developing for Drupal 8
Technologies that drive Drupal
PHP
Databases and MySQL
The web server
HTML, CSS, and JavaScript
Drupal architecture
Drupal core, modules, and themes
Hooks, plugins, and events
Services and the dependency injection container
From request to response
Drupal's major subsystems
Routing
Entities
Fields
Menus
Views
Forms
Configuration
Plugins
The theme system
Caching
Other subsystems
Tools for developing in Drupal
Version control
Composer
The API site and coding standards
The developer (Devel) module
Drush (the Drupal shell)
Drupal Console
Developer settings
Summary
Creating Your First Module
Creating a module
Your first hook implementation
Route and controller
The route
Route variables
Namespaces
The Controller
Services
What is a service?
The HelloWorldSalutation service
Tagged services
Using services in Drupal 8
Injecting the service into our Controller
Invoked Controllers
The form
Altering forms
Custom submit handlers
Rendering forms
Service dependencies
Blocks
Our first block plugin
Block configuration
Working with links
The URL
The link
Which way to link?
Event Dispatcher and redirects
Redirecting from a Controller
Redirecting from a subscriber
Dispatching events
Summary
Logging and Mailing
Logging
The Drupal 8 logging theory
Our own logger channel
Our own logger
Logging for Hello World
Logging summary
Mail API
The theory of the Mail API
Implementing hook_mail()
Sending emails
Altering someone else's emails
Custom mail plugins
The mail plugin
Using mail plugins
Tokens
The Token API
Using tokens
Defining new tokens
Token summary
Summary
Theming
Business logic versus presentation logic
Twig
Theme hooks
Theme hook suggestions
Render arrays
The structure of a render array
#type
#theme
#markup
The render pipeline
Assets and libraries
Libraries
Attaching libraries
Common theme hooks
Lists
Links
Tables
Attributes
Layouts
Defining layouts
Rendering a layout
Theming our Hello World module
Summary
Menus and Menu Links
The menu system
Menus
Menu links
Multiple types of menu links
Local tasks
Local actions
Contextual links
MenuLink trees
Menu link tree manipulators
Menu active trail
Rendering menus
Working with menu links
Defining menu links
Working with menu links
Defining local tasks
Defining local actions
Defining contextual links
Summary
Data Modeling and Storage
Different types of data storage
State API
TempStore
Private TempStore
Shared TempStore
Tempstore conclusion
UserData
Configuration
Introduction
What is configuration used for?
Managing configuration
Different types of configuration
Configuration storage
Schema
Overrides
Global overrides
Module overrides
Language overrides
Priority
Interacting with simple configuration
Entities
Content versus configuration entity types
Entity type plugins
Identifiers
Bundles
Database tables
Entity keys
Links
Entity translation
Entity revisions
Configuration export
Handlers
Fields
Configuration entity fields
Content entity fields
Base fields
Configurable fields
Field storage
Entity types summary
TypedData
Why TypedData?
What is TypedData?
The low-level API
DataType plugins
Data definitions
Content entities
TypedData summary
Interacting with the Entity API
Querying entities
Building queries
Loading entities
Reading entities
Manipulating entities
Creating entities
Rendering content entities
Pseudo-fields
Entity validation
Content entities
Configuration entities
Validation summary
Summary
Your Own Custom Entity and Plugin Types
Custom content entity type
Custom plugin type
Custom configuration entity type
The Importer plugin
Content entity bundles
Drush command
Summary
The Database API
The Schema API
Running queries
Select queries
Handling the result
More complex select queries
Range queries
Pagers
Insert queries
Update queries
Delete queries
Transactions
Query alters
Update hooks
Summary
Custom Fields
A recap of Field type plugins
Field type
Field widget
Field formatter
Field settings
Using our custom field type as a base field
Summary
Access Control
Introduction to the Drupal access system
Roles and permissions under the hood
Defining permissions
Checking the user credentials
Route access
Custom route access
Static approach
Service approach
Programmatically checking access on routes
Bonus—dynamic route options for access control
CSRF protection on routes
Altering routes
Entity access
Injecting services into Entity handlers
Entity access hooks
Field access
Entity access in routes
Node access grants
Block access
Summary
Caching
Introduction to Caching
Cacheability metadata
Cache tags
Cache contexts
Max-age
Using the cache metadata
Caching in block plugins
Caching access results
Placeholders and lazy building
Lazy builders
Using the Cache API
Creating our own cache bin
Summary
JavaScript and the Ajax API
JavaScript in Drupal
Drupal behaviors
Our library
The JavaScript
Drupal settings
The Ajax API
Ajax links
Ajax in forms
States (Form) system
Summary
Internationalization and Languages
Introduction to the multilingual ecosystem
Language
Content translation
Configuration translation
Interface translation
Internationalization
Content entities and the Translation API
Summary
Batches, Queues, and Cron
Batch-powered update hooks
Batch operations
Creating the batch
Batch operations
Cron
Queues
Introduction to the Queue API
Cron-based queues
Processing a queue programmatically
The Lock API
Summary
Views
Entities in Views
Exposing custom data to Views
Views data
Views fields
Views relationships
Views sorts and filters
Views arguments
Altering Views data
Custom Views field
Field configuration
Custom Views filter
Custom Views argument
Views theming
Views hooks
Summary
Working with Files and Images
The filesystem
Stream wrappers
Managed versus unmanaged files
Using the File and Image fields
Working with managed files
Attaching managed files to entities
Helpful functions for dealing with managed files
Managed file uploads
Managed file form element
Entity CRUD hooks
Managed file usage service
Processing the CSV file
Our own stream wrapper
Working with unmanaged files
Private filesystem
Images
Image toolkits
Image styles
Rendering images
Summary
Automated Testing
Testing methodologies in Drupal 8
PHPUnit
Registering tests
Unit tests
Mocked dependencies
Kernel tests
TeamCleaner test
CsvImporter test
Functional tests
Configuration for functional tests
Hello World page test
Hello World form test
Functional JavaScript tests
Time test
CsvImporter test
Summary
Drupal 8 Security
Cross-Site Scripting (XSS)
Sanitization methods in Drupal 8
Double escaping
SQL Injection
Cross-Site Request Forgery (CSRF)
Summary
Other Books You May Enjoy
Leave a review - let other readers know what you think
Drupal 8 is a powerful web-based content management system (CMS) that can be used to build anything from simple websites to powerful applications. While it is useful out of the box, it is designed with developers in mind.
The purpose of this book is to talk about the most common ways a Drupal 8 website can be extended to provide new functionality. In doing so, the book will cover a number of extension points, but also illustrate many subsystems and APIs that can help you model, structure, and wire your business requirements.
Alongside the obligatory theoretical explanations, it will use a practical, example-based approach in order to break down complex topics and make them easier to understand. So, join me on this journey to discover exactly how powerful Drupal 8 actually is.
The primary target audience for this book is Drupal 7 developers who want to learn how to write modules and carry out development in Drupal 8. It is also intended for Drupal site builders who have basic object-oriented programming skills, as well as PHP programmers who have little experience of Drupal.
A little bit of Symfony experience will be beneficial, but isn't mandatory.
Chapter 1, Developing for Drupal 8, provides an introduction to module development in Drupal 8. In doing so, it introduces the reader to the various subsystems and outlines the requirements for running a Drupal 8 application.
Chapter 2, Creating Your First Module, gets the ball rolling with the creation of the first Drupal 8 module of the book. Its primary focus is to explore the most common things module developers need to know from the get-go.
Chapter 3, Logging and Mailing, is about the tools available for doing something every web-based application does and/or should be doing; that is, sending emails and logging events.
Chapter 4, Theming, presents the theme system from a module developer's perspective in Drupal 8.
Chapter 5, Menus and Menu Links, explores the world of menus in Drupal 8 and shows how to programmatically create and work with menu links.
Chapter 6, Data Modeling and Storage, looks at the various types of storage available in Drupal 8, from the state system to configuration and entities.
Chapter 7, Your Own Custom Entity and Plugin Types, takes a hands-on approach in terms of creating a custom configuration and content entity type, as well as a custom plugin type for wiring up a practical functional example.
Chapter 8, The Database API, presents the database abstraction layer and discuss how we can work directly with data stored in custom tables.
Chapter 9, Custom Fields, exemplifies the creation of the three plugins necessary for creating a custom field that can be used on a Drupal 8 content entity type.
Chapter 10, Access Control, explores the world of access restrictions in Drupal 8, from roles and permissions to route and entity access checks.
Chapter 11, Caching, looks at the various cache mechanisms available for module developers to improve the performance of their functionality.
Chapter 12, JavaScript and the AJAX API, introduces module developers to the specificities of writing JavaScript in Drupal 8, as well as the powerful AJAX system, which can be used to build advanced interactions.
Chapter 13, Internationalization and Languages, deals with the practices that Drupal 8 module developers need to observe in order to ensure that the application can be properly translated.
Chapter 14, Batches, Queues, and Cron, explores the various ways module developers can structure their data-processing tasks in a reliable way.
Chapter 15, Views, looks at the various ways module developers can programmatically interact with Views and even expose their own data to them.
Chapter 16, Working with Files and Images, explores the various file and image APIs that allow module developers to store, track, and manage files in Drupal 8.
Chapter 17, Automated Testing, explores the various types of automated test module that developers can write for their Drupal 8 applications so as to ensure stable and resilient code.
Chapter 18, Drupal 8 Security, explores the most common principles that need to be observed when developing Drupal 8 modules.
Readers don't need much to follow along with this book. A local environment setup capable of installing and running Drupal 8 (preferably with Composer) should suffice.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Drupal-8-Module-Development-Second-Edition. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/9781789612363_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Custom Drupal 8 modules typically belong inside the /custom directory of the /modules folder found inside the root Drupal installation."
A block of code is set as follows:
name: Hello World description: Hello World module type: module core: 8.x package: Custom
Any command-line input or output is written as follows:
cd core
Bold: Indicates a new term, an important word, or words that you see on screen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Users can now reach this page from the module administration page by clicking on theHelplink for each individual module that has this hook implemented."
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in, and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
Drupal is a web-based Content Management System (CMS). While it is useful out of the box, it is designed with developers in mind. The purpose of this book is to explain how Drupal can be extended in many ways and for many purposes. To this end, the version we will use will be the latest one at the time of writing this book—Drupal 8.7.
In this book, we will cover a wide range of development topics. We'll discuss how to create a Drupal 8 module, and as we go through the chapters, many concepts and tips that will help you build what you need. The goal is not only to explain how things work but also to go through some examples in order to demonstrate them. Since no book can contain everything, I hope that after reading this book, you'll be able to expand on this knowledge on your own using the resources I reference and by looking into the Drupal core code itself. As helpful as such a book can be for learning any kind of software development, if you really want to progress, you will need to apply the knowledge you learned and explore the source code yourself. Only by doing this will you be able to understand complex systems with many dependencies and layers.
This chapter introduces the terminology, tools, and processes for developing Drupal 8. While subsequent chapters focus on code, this chapter focuses on concepts. We'll talk about the architecture of Drupal and how you can hook into Drupal at strategic places to extend it for accomplishing new tasks.
The following are the major topics we will be covering in this chapter:
An introduction to Drupal development
Drupal 8 architecture
The major subsystems of Drupal
Tools for developing in Drupal
By the end of this chapter, you will understand the architectural aspects of Drupal and be ready to start writing code.
Out of the box, Drupal traditionally has all the standard functions of a web-based content management system:
Visitors can view published information on the site, navigate through menus, view listings, and individual pages and so on
Users can create accounts and leave comments
Administrators can manage the site configuration and control the permissions of users
Editors can create, preview, and then publish content when it is ready
Content can be syndicated to RSS, where feed readers can pick up new articles as they are published
With several built-in themes, even the look and feel of the site can be easily changed
However, Drupal 8 improved on these and introduced some more powerful capabilities. For example, advanced multilingual support, content moderation, layout building, REST API and many other features are now available out of the box.
As fantastic as these features are, they will certainly not satisfy the needs of all users. To that end, Drupal's capabilities can be easily extended with modules, themes, and installation profiles. Take a look at Drupal's main website, (http://drupal.org), and you will find thousands of modules that provide new features and thousands of themes that transform the look and feel of the application or website.
The flexible way Drupal can be extended and transformed through the module and theme mechanisms has led many to claim that Drupal isn't just a CMS, but a Content Management Framework (CMF) capable of being re-tooled to specific needs and functional requirements. This is particularly the case with Drupal 8—the latest version of Drupal and the focus of this book—as great progress has been made on the extensibility front as well.
Establishing whether Drupal is rightly called a CMS or CMF is beyond our purpose here, but it is certain that Drupal's most tremendous asset is its extensibility. Want to use a directory server for authentication? There's a Drupal module for that. Want to export data to Comma-separated Version (CSV) files? There are several modules for that (depending on what data you want to export). Interested in Facebook support, integration with Twitter, or adding a Share This button? Yup, there are modules for those too—all of which are available on Drupal.org and provided by developers like you.
Want to integrate Drupal with that custom tool you wrote to solve your special business needs? There may not be a module for that, but with a little bit of code, you can write your own. In fact, that is the subject of this book—providing you with the knowledge and tools to achieve your own goals.
In summary, the purpose of this book is to get you ramped up (as quickly as possible) for Drupal 8 module development. As we move chapter by chapter, we will cover the APIs and tools that you will use to build custom Drupal sites, and we won't stick to theory. Most chapters provide working, practically-oriented example code designed to show you how to implement the concepts we will be talking about. We will follow Drupal coding conventions and utilize Drupal design patterns in an effort to illustrate the correct way to write code within the Drupal development context.
While I certainly can't write the exact code to meet your needs, my hope is that the code mentioned in these chapters can serve as a foundation for your bigger and better applications.
So let's get started with a few preliminary matters to better understand Drupal.
Installing Drupal 8 in the traditional way is documented both on Drupal.org and in the INSTALL.txt file found inside the /core folder of the installation, so I won't go into it here. I will, however, mention that a better way of installing Drupal 8, especially for developers, is by using the accepted Composer template for Drupal 8 projects found on GitHub (https://github.com/drupal-composer/drupal-project). However, the instructions for setting up your site are well covered there as well.
Instead, let's talk a bit about the technologies that power (or are needed by) Drupal 8.
Drupal is written in the PHP programming language. PHP is a widely supported, multiplatform, and web-centric scripting language. Since Drupal is written in PHP, this book will largely feature code written in PHP, albeit with Drupal standard practices being kept in mind.
It is very important to note that the minimum version of PHP required for Drupal 8 to run (and install via Composer) is 7.1. Therefore PHP 5 is no longer supported, neither by Drupal nor by the PHP community at large. By the time you read this book, you should probably be running Drupal on PHP 7.3 or at least 7.2
Regarding the style of PHP, a very important change compared to Drupal 7 is the heavy use of object-oriented code and design patterns. Granted, many procedural style approaches remain throughout the Drupal 8 code base, but the use of a good number of popular external libraries (such as Symfony components) has pushed the overall Drupal code to be more modern. For this reason, it is also quite important that you have at least some basic understanding of Object-Oriented Programming (OOP), especially PHP-related, if you want to do Drupal 8 development.
In the past, Drupal has supported two databases—MySQL and PostgreSQL. Drupal 7 and 8 have moved beyond this. Drupal now uses the powerful PHP Data Objects (PDO) library that is standard in PHP 7. This library is an abstraction layer that allows developers to support numerous databases, including MySQL, PostgreSQL, SQLite, and MariaDB.
The minimum database versions for Drupal 8.7 are as follows:
MySQL 5.5.3/MariaDB 5.5.20/Percona Server 5.5.8 or higher with PDO and an InnoDB-compatible primary storage engine
PostgreSQL 9.1.2 or higher with PDO SQLite 3.7.11 or higher
SQLite 3.7.11 or higher
Additionally, Drupal provides a powerful database API along with SQL coding conventions that make it easy to interact with your database—which, combined, allow you to write safe and portable SQL. However, more and more abstractions have been made at different levels, removing the need for SQL writing almost completely. However, we will still see some examples just so your toolbox does not miss anything, as well as cover all the tools at your disposal for querying your database.
Apache has long been the predominant web server, but it is by no means the only server. While Drupal was originally written with Apache in mind, many other web servers (including IIS, Lighttpd, and NGINX) can run Drupal.
We do not explicitly cover the web server layer anywhere in this book, primarily because development rarely requires working at that low level. However, Drupal expects a fair amount of processing from the web server layer, including the handling of URL rewriting. For more information on what you can expect, you can consult the relevant documentation page at https://www.drupal.org/docs/8/system-requirements/web-server.
The de facto web data format is HTML styled with Cascading Style Sheets (CSS). Client-side interactive components are scripted with JavaScript. As Drupal developers, we will encounter all three of these technologies in this book. Although you don't need to be a JavaScript ninja to understand the code here, you will get the most from this book if you are comfortable with these three technologies.
In the preceding section, we introduced the technologies that drive Drupal. However, how do they all fit together? How is Drupal code organized? In this section, we provide an overview of Drupal's architecture, with a focus on Drupal 8.
From an architectural standpoint, we can break up Drupal into three pieces: its core, modules and themes.
When we discuss Drupal 8 core, we can interpret it in two ways. A more restrictive interpretation sees it as the functionality covered by all the code it ships with, excluding modules and themes. The more widespread interpretation sees it as the total code base it ships with (out of the box).
Although the most widespread interpretation is the latter (not least because it differentiates all the functionalities its standard installation contains versus all others provided by contributed modules and themes), it is interesting to consider the first one as well, even if just for a minute. Because in doing so we can distinguish, architecturally speaking, the base code from the modules and themes that provide various functionalities and layouts. And why is this distinction interesting? Because at the bridge between the two comes into play the hooks and events that will also allow us to inject ties to our own functionality.
The core libraries are made up of code belonging to the Drupal project and those from the wider PHP community, which Drupal borrows under open source licensing. This latter approach is new in Drupal 8 and has been regarded by many as a positive shift toward getting off the Drupal island and embracing outside libraries, frameworks, and communities.
Essentially, the core libraries provide the functions and services used throughout Drupal. For example, helpers for interacting with the database, translating between languages, sanitizing user data, building forms, encoding data, and many such utilities are found in Drupal's core libraries.
The modules (both core and contributed) are where most of the actual business logic is encapsulated. If enabled, they can provide functionality or extend the existing one. Most of the core modules are needed and cannot be disabled due to their importance in the standard Drupal installation. However, contributed ones can be installed and uninstalled as needed.
The themes (both core and contributed) are an important part of the theme system and are used by the presentation layer. They provide HTML templates within which content and data can be rendered to the user, as well as CSS styling and even client-side scripting for some nice visual interactions. Themes can extend other themes and can also contain some PHP logic to process the data before being rendered.
Now that we have seen what the core libraries, modules, and themes do, let's talk briefly about hooks and events to understand how they are all connected.
Hooks are a very typical Drupal procedural concept that allows Drupal core and modules to gather data from other modules and themes (or expose it). By doing this, the latter can provide new functionality or alter existing ones. It is the responsibility of the code that invokes the hook to make use of whatever the hook implementations return. The format for whatever the latter need to return is usually described in the hook documentation.
Concretely, hooks work by scanning installed modules and themes and looking for a function that follows a specific naming pattern (in other words, a hook implementation). This is, in most cases, in the following format—module_name_hook_name. Additionally, there are also alter hooks, which have the word alter tacked on the end of the function name and are used to change data passed as a reference to the hook implementation. We will see examples of hooks later in the book.
In previous versions of Drupal, hooks were KING. Yes, I wrote this in capital letters; my Caps Lock did not get stuck. This is because they were the way to add or extend functionality in modules. As such, they were the single most important aspect of Drupal programming. In Drupal 8, however, although still important, they took a backseat to new concepts, such as plugins and events.
In Drupal 8, I dare to say that plugins are king. Much of the logic that used to be tied to Drupal via hooks is now added in through plugins (not to be confused with WordPress plugins). Drupal 8 plugins are discoverable bits of the functionality centralized by a manager and that are used for certain tasks and features. We will see more about plugins and provide many examples later in the book.
A third extension point introduced in Drupal 8 is the event system. Unlike the first two, however, this is not specific to Drupal, but is, in fact, the actual Symfony EventDispatcher component (http://symfony.com/doc/current/components/event_dispatcher.html). Events are primarily used in Drupal to intercept certain actions or flows in order to either stop or modify them. Many request to response tasks that were handled via hooks in the past are now being handled by dispatching events to check whether any modules are interested in, for example, delivering the response to the user.
Another architecturally important element of Drupal 8 is the Symfony dependency injection component (http://symfony.com/doc/current/components/dependency_injection.html), specifically represented by the service container.
This component is a staple of modern OOP PHP programming and as such has become foundational to Drupal 8. It allows us to create services that can be injected in various places of our code in order to handle certain functional (and oftentimes swappable) tasks. Additionally, they can also be used as an extension point because the service container is able to group services that have very specific responsibilities and use them for that automatically. In other words, simply by defining a simple service, we can provide our own functionality or even change existing logic.
We will encounter many services, and we will see how we can declare our own later in this book.
Now that we have listed the most important architectural pieces of Drupal, let's briefly see how these are used in delivering responses to the requests a user makes on a Drupal 8 website. To this end, we will analyze a simplified example of a request as it is handled on a Drupal 8 website:
A user accesses the
http://example.com/node/123
URL in a web browser.
The browser contacts the web server at
example.com
and requests the resource at
/node/123
.
The web server recognizes that the request must be handled by PHP and starts up (or contacts) a PHP environment to handle the request.
PHP executes Drupal's front controller file (
index.php
), which then creates a new
Request
object from the resource that was requested.
Symfony's HTTPKernel handles this request object by dispatching a number of events, such as
kernel.request
,
kernel.controller
,
kernel.response
, and
kernel.view
.
The route that maps to that request is identified through the
kernel.request
event.
The route controller is identified, and the
kernel.controller
event is used to perform any alterations on the responsible controller, as well as to resolve the arguments that need to be passed to it. In our case, this route is registered by the Node module through the main Entity system, which identifies the entity ID, loads it, and builds the markup to be returned as part of the response.
If the respective controller (or handler) returns something other than a response object, the
kernel.view
event is dispatched to check whether there is any code that can transform that into a Response object. In most cases, in Drupal 8, we typically return render arrays, which are transformed into Response objects.
Once a Response is created, the front controller returns it to the browser and terminates the request.
In this context, as Drupal 8 module developers, we spend most of our time inside controllers and services, trying to figure out what we need to return to the page. We then rely on Drupal to transform our render array into a proper response to the user, but we can also return one ourselves directly. Moreover, the theme system comes into play here, as well as the block system, because our content gets wrapped into a block that is placed in a region surrounded by other regions that contain other blocks. If it sounds complicated now, don't worry; we will cover in detail all these aspects with examples, and it will become clear in no time.
In the previous we took a bird's-eye view of Drupal's architecture. Now, we will refine our perspective a bit. We will walk through the major subsystems that Drupal 8 has to offer.
It all starts with a route, doesn't it? Most interactions with a Drupal 8 website begin with a user (or system) accessing a certain path (or resource). This translates into a route, which maps that resource to a flow that (hopefully) returns a successful response back or at least a graceful failure.
The Drupal 8 routing system is a major shift away from how it used to be in its previous versions. In Drupal 7 and before, the routing system was a very Drupal-specific thing (a drupalism, if you will). Many of us remember hook_menu as a staple hook each Drupal developer had to know very well. All of that has been abandoned in Drupal 8 in favor of the Symfony Routing component (http://symfony.com/doc/current/components/routing.html). Also, since I mentioned hook_menu, I will also mention that its other main functions have also been taken over in Drupal 8 by other subsystems, such as plugins.
In Chapter 2, Creating Your First Module, we will see how we can define our own route and map it to a controller that will render our page. We will cover a few of the more important route options and take a look at how we can control access to these routes.
Progressively, entities have become a very powerful way of modeling data and content in Drupal. The most famous type of entity has always been the Node, and it has been historically the cornerstone of content storage and display. In Drupal 8, the entire entity system has been revamped to make other entity types potentially just as important. They have been brought to the forefront and have been properly connected with other systems.
All entity types can have multiple bundles, which are different variations of the same entity type and can have different fields on them (while sharing some base fields).
Drupal core still ships with the Node entity type, with a few bundles such as Basic Page and Article in its standard installation profile. In addition, it comes with a few other entity types, such as User, Comment, and File. However, creating your own entity type in Drupal 8 has become much more standardized compared to Drupal 7 where contributed modules had to be brought into play.
These are not the only types of entities we have in Drupal 8. The aforementioned examples are all content entity types. Drupal 8, however, also introduced the configuration entity types. The former are for modeling content, but in reality, they are for anything that holds data that can be stored in the database and is specific to that environment. They are not used for storing configuration, though. Users and content are great examples, as they do not need to be (usually) deployable from one environment to another. The latter, on the other hand, are exportable items of configuration, of which there can be more than one. For example, a content entity bundle is a great example because there can be more than one bundle for a certain entity type; they have some metadata and information stored that can differ from bundle to bundle, and they need to be deployed on all environments. That is, they are fundamental to the correct functioning of the site.
Understanding the entity system is indispensable for doing development in Drupal 8 because it provides a powerful way to model custom data and content. Nodes are not the only tool for the job and in my opinion, they were used in previous Drupal versions way past their purpose due to the lack of a proper entity architecture.
Now that we have an idea of what entities are, let's take a look at how data is actually stored on these entities.
I have alluded in the preceding section to how certain entity bundles can have various fields. This means that each entity type bundle can have any number of fields that are responsible for holding data. Additionally, each entity type itself can have fields for storing data. Okay, but what? Let's break this down.
There are two types of fields in Drupal 8—base fields and configurable fields. The former are fields that are defined in the code for each entity type, whereas the latter are usually created and configured in the UI and attached to a bundle of that entity type (and exported via configuration).
Fields can also be of multiples types, depending on the data they store. You can have string (or text) fields, numeric fields, date fields, email fields, and so on. As developers, we can create our own field types if the existing ones are not good enough for our data.
In this book, we will take a look at how we can define base fields on a certain entity type and create our own field type with its own data input widget and output formatter. Site builders can then use this field type on any entity type.
Any site needs some sort of navigation, right? Drupal not only maintains content, but also provides details about how the site itself is organized. That is, it keeps a structure of how content is related.
The principal way that it does this is through the menu subsystem. The latter provides APIs to generate, retrieve, and modify elements that describe the site structure. Put in common parlance, it handles the system's navigational menus.
Menus are hierarchical, that is, they have a tree-like structure. A menu item can have multiple children, each of which may have their own children, and so on. In this way, we can use the menu system to structure our site into sections and subsections.
In this book, we will see how we can work programmatically with menus and menu links.
Listing content and data is always an important capability content management systems covet; and this is what Views does in Drupal 8. And it does it well.
If you've been building (not even necessarily developing) sites in previous versions of Drupal, you'll understand everything with this simple phrase—Views is now in Drupal core.
If you haven't, Views has always been a staple Drupal contributed module used on probably all Drupal installations (to a certain extent) and is an indispensable tool for site builders and even developers.
The purpose of the Views module is to expose data and content in a way that allows the creation of configurable listings. It includes things such as filters, sorts, display options, and many other features. As developers, we often find a need to write our own field or filter plugin to work with Views or expose data from our custom entities or external data sources.
Views is a core Drupal 8 module tied to the general architecture and used for most list pages (especially, admin pages) provided by Drupal core. Although it's a very site building-oriented tool, in this book, we will take a look at how we can create plugins that extend its capabilities to offer site builders even more.
Unless your site has three pages and five paragraphs of text, the likelihood that you will need to capture user input via some type of form is very high. Also, if you've been coding PHP applications you know how forms have always been a pain from the point of view of securely and efficiently rendering and processing the submitted data. As soon as you use a PHP framework such as Symfony or Laravel, you will note that an API is in place to take much of that load off your shoulders.
The same goes with Drupal 8 and its powerful Form API. Historically, it has been a great abstraction over having to output your own form elements and deal with posted values. It allows you to define your own form definition in OOP and handle validation and submission in a logical way. Its rendering and processing is taken care of by Drupal securely, so you don't have to worry about any of that. In Drupal 8, theming form elements has become much easier than in previous versions.
In this book, we will encounter some forms and see how they actually work in practice.
One of the major pet-peeves of Drupal developers (and developers of other popular CMSes for that matter) has always been the way configuration is handled and deployed from one environment to the next. Drupal 7 stored most of its configuration in the database, so various solutions had to be concocted by developers to get that moved up the ladder as development progressed.
In Drupal 8, great advancements have been made in this respect with the introduction of a centralized configuration system. Although it stores all configuration in the database, it allows it all to be exported into YML files (and then reimported). So, from a development point of view, we have a much better experience if certain features depend on configuration (for example, a new field).
Configuration is also of two kinds—simple and complex (configuration entities we noted in the Entities section). The difference between the two is that the former is always singular. In other words, there is only one instance of itself. For example, the site name and email address are stored inside such a configuration item. You wouldn't expect the need for more than one instance of it. However, in the case of the latter, you would. For example, a View definition is such a configuration entity because it follows a certain schema and we can have multiple View definitions. Makes sense doesn't it?
Plugins are new to Drupal 8 and are an elegant solution to an important problem— encapsulating functionality. Right off the bat, you should not confuse them with things such as the WordPress plugins, which are more akin to Drupal modules. Instead, you should think of plugins as components of reusable code that can be used and managed by a central system. Typically, they are used when a system handles a task in a certain way (plugin A) but allows other modules to provide different ways to handle that task (plugin B or C).
You can also look at plugins as being opposite to entities: not used for data storage, but for functionality. Instead of creating a type of data that gets stored, you create a type of functionality that is used. The two usually work hand in hand, especially when it comes to manipulating the data in different ways.
An important aspect of how they work is their discoverability. Most plugin types (but definitely not all) are discovered via something called Annotations. Annotations are a form of DocBlock comments, borrowed from the Doctrine library (http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html), by which we can describe classes, methods, and even properties with certain metadata. This metadata is then read to determine what that item is without the need for instantiating the class. In Drupal 8, we use annotations only at a class level to denote that it is a plugin implementation with certain characteristics. That is how most plugins are discovered in Drupal 8.
The second most common discoverability method for plugins is via a YAML file, and a popular example of those are menu links (as we will see later in the book). However, for now, you should know that plugins are very widely used, and we will create quite a few plugins in this book.
Plugins are a great new extension point for developers to add their own functionality and are a critical subsystem in Drupal 8. Every Drupal 8 developer needs to be comfortable with the plugin system.
The responsibility for theming a given piece of data is spread out over the Drupal core, modules, and the themes themselves. So, as a module developer, it is important to know that both modules and themes can theme data or content.
In this book, we will focus on the aspects that happen at the module level. We will not concern ourselves with styling, but work primarily with theming definitions and templates that are needed within the module. Typically, it is best practice to ensure that modules are able to theme their data. If done right, themes can then come into play to style the output or override that theming to change the presentation altogether.
A major shift in Drupal 8 compared to older versions is the move to the open source Twig templating system (https://twig.sensiolabs.org/). This makes the separation of logic from a presentation that much clearer and makes frontend developers jobs much easier, not to mention more secure.
The last major subsystem that I will include here is the caching layer. Drupal 8 has gone to great lengths to improve the performance of building pages and rendering data. To this end, the caching system has become an important part to consider whenever we either do complex or heavy calculations or render content.
From a module developer's perspective, there are two main pillars of the caching system. The first one provides developers with a cache backend to store the results of complex data calculations. This can be read in the next requests to avoid the need for reprocessing that task. This goes hand in hand with the cache invalidation that happens when something in the system changes that would require the calculations to be redone. The second pillar is the render cache, which allows developers to wrap their output with metadata that describes when the cache of that output needs to be invalidated.
We will see these in action in a later chapter dedicated to caching.
There are other subsystems in Drupal 8 of varying importance. I chose to include the previous ones because I deemed them to be the most important to be introduced up front and especially from the point of view of a module developer. However, as we progress through the book, we will definitely encounter others.
Drupal is a sophisticated platform, and from the glimpse provided in this chapter, we can already see that there are numerous systems and structures to keep track of. In this section, I will provide tools that simplify or streamline the development process.
Going forward, I assume that you have your own web server stack and your own PHP development tools. However, if you are just getting started, you may want to look at Acquia Dev Desktop from Acquia (http://acquia.com). It offers entire application stacks to get you started on Windows, Linux, or macOS X. Alternatively, if you are even just a bit more advanced, you can consider the Drupal VM (https://www.drupalvm.com/), a Vagrant and Ansible-based local development environment ready for Drupal.
Finally, the most flexible development environment in my opinion is the Docker-based one. You can easily get started with a pre-made and well documented stack here: https://github.com/wodby/docker4drupal.
As for a code editor, I personally use PhpStorm (as many others do), but you are free to use whatever IDE you want because Drupal itself doesn't require anything special. Do, however, use some sort of an IDE because it will make your life much easier.
Additionally, while running a PHP debugger is certainly not necessary, you may find running Xdebug or the Zend Debugger to be useful. I personally recommend a PHP debugger wholeheartedly, not only for debugging itself, but also for understanding the processes that happen under the hood.
Any software development needs to happen through a version-controlled environment. By now, Drupal is universally using Git. So, you should make sure that you have Git installed locally, even if just to be able to check out the code examples we write in this book, which are hosted on GitHub.
As I alluded to earlier, installing Drupal 8 is best done via the Composer template project. However, you may also install it straight from Git by checking out the latest tag or commit in the Drupal.org Git repository (https://www.drupal.org/project/drupal/git-instructions). If you do this, you will need to install its dependencies via Composer, and Drupal has many.
To this end, you will need to have Composer available on your development environment and have a basic understanding of how to use it.
A lot of background knowledge is required for writing good Drupal code. Of course, the aim of a book such as this is to try to provide as much of that background knowledge as possible. However, self-documentation and research still remain key, and there are a number of resources that a Drupal developer should have on-hand.
The first is the official online API documentation. Just about every function in Drupal is documented using inline code documentation. The Doxygen program is then used to extract that documentation and format it. You can access the full API documentation online at http://api.drupal.org.
Along with using the Drupal APIs, we strive to comply with Drupal's coding conventions. Best practices in software development include keeping code clean, consistent, and readable. One aspect of this is removing nuances in code formatting by following a fixed standard.
This is particularly important on a platform such as Drupal, where thousands of developers all contribute to the code. Without coding standards, the code would become a cluttered mishmash of styles, and valuable development time will be spent merely deciphering code instead of working on it.
The Drupal site has a manual on coding standards that each Drupal developer needs to become familiar with (https://www.drupal.org/docs/develop/standards/coding-standards). It won't happen overnight; you will get better with experience, but you can also configure your IDE to, for instance, flag any issues with your code formatting.
A third resource for developers new to Drupal 8, but who have experience with Drupal 7, is the change records database (https://www.drupal.org/list-changes/drupal
