One of the problems that Drush solves for developers is the automation and optimization of routine tasks. Drush commands attempt to speed up workflows and tasks that developers and site maintainers would otherwise have to do manually through the UI, or run one-by-one via the command line. One of those tasks is the process of deploying changes to a Drupal application from one environment to another.
The typical Drupal deployment process consists of repeatable steps such as importing configuration changes, applying database updates, and clearing the cache. Drush comes with the handy drush deploy
command that allows you to automate the execution of all of these tasks post code deployment.
In this tutorial we'll:
- Learn about the
drush deploy
command - Discuss when you would use the
deploy
command
By the end of this tutorial you'll know how to use the drush deploy
command in conjunction with other useful deployment-related commands to help automate the task of deploying changes to a Drupal site's configuration and code.
Code generators are great productivity boosters that allow generating scaffolds for common development tasks in Drupal. One of the most common use cases for generators is scaffolding the code required for a custom entity type. Custom entities require many files and complicated annotations in order to function properly. There is a lot of boilerplate code that is more-or-less the same for every entity type. Creating all the files is repetitive, time-consuming, and prone to human error. Generators can help automate this task and make creating your own custom entity types quicker.
In this tutorial we'll:
- Learn how to generate the code for a custom entity with Drush
- Learn about the options that generators provide for custom entities
By the end of this tutorial you should know how to generate custom entities with Drush.
Some Drush commands return a lot of information -- lists of modules, generators, and status reports, for example. It might be hard to find a property you need in the small command window output. Luckily, the output of Drush commands can be piped to other commands, used as a source for imports, settings for CI, and other DevOps tasks.
In order to accommodate all these different use cases, Drush comes with a formatting system that allows you to format and filter output to meet your needs. This system allows to you specify what fields you want returned when the output contains more than one field. It also allows Drush command output to be formatted as JSON, XML, raw PHP, a table, and more.
In this tutorial we'll:
- Learn how to specify the output format -- and what formats are available
- Limit the fields that are returned in a report
- Learn to filter the output to only the data we're interested in
By the end of this tutorial you'll know how to format a Drush command's output to fit your needs.
If you want to change the way an existing Drush command works you use hooks. Hooks are useful for altering command parameters, options, annotation data, and adding custom logic during particular stages of the command execution process. Drush hooks are conceptually similar to Drupal hooks.
Hooks are methods on a Drush command class with an annotation indicating what hook is being implemented, and thus when the code should be invoked. The code in the methods is executed during specific stages of the command cycle. Developers can use core hooks -- predefined methods that come with Drush core -- or declare a custom hook that other commands can use.
In this tutorial we'll:
- Explore the different core Drush hooks
- Learn which hooks are called at what stage of the command cycle
- View example hook annotations and method implementations
By the end of this tutorial you'll know what types of core hooks are available to you and when they are called.
Adding logging and error handling are an important part of authoring Drush commands. Logs allow developers to get timely feedback from a command and inform users about potential alterations and flags, events to monitor, and the progress of long-running commands. Correct error handling allows for clean exits, meaningful error descriptions, and provides a path forward for developers to fix the errors and accomplish their goals.
In this tutorial we'll:
- Explore the different types of logging messages Drush commands can output
- Learn how to handle errors from within a Drush command
By the end of this tutorial you'll know what types of log messages you can use; how to log success messages, errors, or debug statements from a custom Drush command; and how to handle errors and exceptions.
When the logic of a command depends on user input, it's useful to set up an interactive questionnaire inside the command code. This allows you to provide the user with more context about the input they're providing, and ensure that you collect all the necessary values. This is especially useful when the command uses a pre-defined list of options and the values require memorization. An example of this is the drush cache-clear
command that comes with Drush core. It requires an argument indicating which cache to clear, which you can specify at the command line; however, if you invoke the command with no arguments it will present you with a list of cache bins to choose from and a UI for selecting one.
Drush 9+ can access the Input/Output (I/O) object via the $this->io()
method. This object -- an instance of \Drush\Style\DrushStyle
-- holds information about user-provided input, and utilities for manipulating that input. To ask a user a question, use an io()
object in the command callback method. It can take over the execution flow of the command as needed to stop and gather additional input. The I/O system has various methods for asking confirmation or choice questions such as confirm()
and choice()
.
In addition to prompting for input, the I/O object can be used to provide other styling to the command, like progress bars.
In this tutorial we'll:
- Learn how to prompt the user for additional input
- Process the user's answer as part of the command execution flow
By the end of this tutorial you should understand how to prompt a user for additional input for a custom Drush command.
While Drush empowers all Drupal users with its commands, it's even more powerful when used in combination with scripting solutions such as Composer and Bash. Scripts can be used to power post-deployment tasks like importing new configuration or clearing the cache, as part of CI processes to sync a database from one environment to another, to run background processes on the server such as imports and migrations, search indexing, running cron, and much more. If you want to write Bash (or any other scripts) that interact with a Drupal site, then Drush is the tool for you.
In this tutorial we'll:
- Learn how to use Drush commands within Composer and Bash scripts
- Learn how to chain multiple Drush commands together in a script
By the end of this tutorial you'll know how to use Drush as part of a script that automates common or tedious tasks.
When you manage many Drupal websites, you may perform repetitive tasks that are common across all of your sites. In our experience, this usually relates to having a personal preference for how certain tasks are accomplished. For example: maybe you like to make backups of the database and files in a specific way before testing upgrades, or you have a set of scripts for running scans of core web vitals. Although these tasks can be bundled into a custom module, it could be useful to create a site-wide Drush command instead. Site-wide commands can be installed with Composer, managed in a separate Git repository, and act as a project dependency. This way they are easy to maintain through a separate upstream. Changes to this code will be reflected on all the sites where it's used.
In this tutorial we'll:
- Declare a custom site-wide Drush command
- Demonstrate how to use Composer to manage a package that contains a Drush command
By the end of this tutorial you'll be able to create a site-wide Drush command and manage the code with Git and Composer.
Creating a container set to support Drupal development requires some specialized knowledge. Now that we understand containers, images, how to use Docker Compose (docker-compose
), and how to select images on Docker Hub, we're ready to build a container set to support Drupal development.
In this tutorial, we'll:
- Select images of software that we'll need to run Drupal
- Create a new Compose file
- Configure bind volumes and environment variables to support the site
- Test the configuration
See Dockerize an Existing Project if you already have Drupal installed.
Customizing the available regions in your theme is one of the first things you'll do when creating your own themes. Doing so gives you complete control over where content is displayed on the page, and the markup involved. Adding regions to a theme is a two-step process that involves editing your theme's THEMENAME.info.yml file and updating your page.html.twig file.
In this tutorial we'll:
- Declare one or more new regions in our themes THEMENAME.info.yml file.
- Output the content of those regions in our theme via the page.html.twig file.
By the end of this tutorial you should be able to add or edit the regions a theme provides. Also, you'll ensure that blocks placed into regions are displayed by outputting the regions in the page template.
Contributed and custom themes can ship with a thumbnail screenshot that will be used to represent the theme when listing themes in the administration UI.
In this tutorial you'll learn how to:
- Prepare your site for the screenshot
- Create a screenshot of your theme
- Define a screenshot file for your theme in the THEMENAME.info.yml file
Preprocess functions are specially-named functions that can be used to add new variables to a Twig template file. They are commonly used by themes to add new variables based on custom PHP logic and simplify accessing the data contained in complex entity structures. For example: adding a variable to all node.html.twig template files that contains the combined content a couple of specific fields under a meaningful name like {{ call_to_action }}
. Modules use preprocess functions to expose the dynamic data they manage to Twig template files, or to alter data provided by another module based on custom logic.
In this tutorial we'll learn how to:
- Use PHP to perform some complex logic in our theme.
- Store the resulting calculation in a variable.
- Make that variable available to a Twig template file.
Example use cases for adding variables with preprocess functions include:
- Anytime calculating the value to output in a template requires logic more complex than an if/else statement.
- Anytime the desired value requires additional string manipulation beyond what can be easily accomplished using an existing Twig filter or function.
By the end of this tutorial you should be able to expose new variables to a Twig template file by defining a preprocess function in either a module or a theme.
Twig has a special syntax for accessing array keys and objects, also known in Twig as variable attributes. In this tutorial, we'll cover the period or dot (.
) operator to access a variable attribute, as well as subscript or square-bracket syntax, useful for when the key of the array contains special characters, like a dash (-
) or pound sign (#
). We'll also look at the logic Twig uses to find the matching attribute in an array or object.
Once you've defined an asset library you'll need to tell Drupal when you want to add the CSS and JavaScript that it includes to the page. Ideally you'll do so in a way that allows Drupal to only add the corresponding assets on pages where they are needed.
You can attach a library to all pages, a subset of pages, or to elements in a render array. This allows you to have some assets that are global, and others that get loaded on an as-needed basis. To attach a library you'll need to know both its name and prefix, and then use one of the techniques outlined below to let Drupal know when to include it.
In this tutorial, we'll look at attaching asset libraries:
- Globally, via your THEMENAME.info.yml file
- Conditionally, via a preprocess function using the
#attached
render array property - Inside of a Twig template file
By the end of this tutorial you should be able to attach asset libraries in various different ways depending on your use case.
It's probably not too surprising that a library called Backbone aims to provide structure to your front-end JavaScript code and applications. In this tutorial we'll take a look at how Backbone.js goes about achieving that goal, and how you can make use of it on your Drupal site. We'll first take a high-level look at the main components that make up the Backbone.js library. With that basic understanding in place we'll look at an example of how you might integrate Backbone.js into a Drupal site.
Drupal's Breakpoint module defines a "breakpoint" plugin type that modules or themes can implement via a breakpoints configuration file. So, in order to make their breakpoints discoverable, themes and modules define their breakpoints in a THEME-OR-MODULE.breakpoints.yml file located in the root of their directory.
In this tutorial, you'll learn about the structure of a breakpoints configuration file and why you would want to use one. We’ll cover the kinds of metadata you can include in a breakpoint file, including key, label, mediaQuery, weight, multipliers, and breakpoint group. Throughout, we'll look at some examples of breakpoint configuration files available in Drupal themes and modules.
You've got a slick responsive theme for your Drupal site that's been implemented in CSS using media queries. But the content and images on your site will regularly be updated and you want to use the Responsive Images module to create responsive image style field formatters that you can apply to image field display settings.
In this lesson, we'll review the concepts of breakpoints and media queries so that you can better understand what's going on when you encounter them in non-CSS file contexts like configuration forms for responsive image styles or breakpoint YAML files.
By the end of this tutorial, you should have an understanding of what breakpoints are, how they are expressed in media queries, and how they are relevant in the context of Drupal.
Some, but not all, themes come with administrator-configurable settings that you can change through the UI. These might allow you to upload your own logo, choose between a couple of different pre-defined layouts, or turn features of a theme on or off. In this tutorial we’ll look at where you can find these theme settings if they exist, and how to go about changing them.
Preprocess functions are specially-named PHP functions that allow themes and modules to modify the variables passed to a Twig template file. They are commonly used by themes to alter existing variables before they are passed to the relevant template files. For example; Changing the makeup of render array so that it renders an <ol>
list instead of a <ul>
list. Or appending data to the label of a node depending on custom logic.
In this tutorial we'll:
- Define a new preprocess function in our theme's .theme file
- Use the preprocess functions to modify the content of an existing variable before it's used in Twig
By the end of this tutorial you should be able to define new preprocess functions in a theme (or module) that manipulate the variables for a specific Twig template file.
Theme developers often need to add or remove classes and other attributes from an HTML tag. Template files handle this with a special Attributes object that contains the attributes and their values, as well as a handful of powerful methods to help manage these attributes.
In this tutorial we’ll cover:
- Adding/removing classes from elements in a Twig template
- The attributes object
- Examples of common tasks using various helper methods on the attributes object