
Unit tests are the simplest among Drupal's test types, ideal for verifying code that performs computations. This tutorial guides through writing unit tests for the anytown module, focusing on the ForecastClient
service, and illustrates how to use mocks for dependencies.
In this tutorial, we'll:
- List potential unit tests for the anytown module.
- Write tests for
ForecastClient
service logic. - Demonstrate how to mock services in unit tests.
By the end of this tutorial you should be able to write PHPUnit Unit tests for logic in the anytown module.
As of Drupal 10.2, most plugin types use PHP attributes for discovery and metadata.
In this tutorial, we'll:
- Provide a recipe for implementing PHP attribute-based plugins.
- Demonstrate how to figure out where the code and metadata should live for PHP attribute-based plugins.
By the end of this tutorial you should have a recipe for getting started with implementing PHP attribute-based plugins, and a better understanding of how to figure out the details required to implement a given plugin type.
PHP attributes are a native PHP language feature, introduced in PHP 8.0, that provide a way to add metadata to classes, methods, properties, and functions in PHP code.
In Drupal, this metadata is used by the plugin system to aid in the discovery and configuration of plugin instances. As a Drupal developer, it's important to understand how to recognize, read, and write PHP attributes, as you'll encounter them when working with plugins.
In this tutorial we'll look at:
- What PHP attributes are
- The use case for attributes in Drupal
- An overview of the attribute syntax
By the end of this tutorial, you should understand how attributes are used in Drupal and how to write them in your own code.
Prior to Drupal 10.2 most plugin implementations required the use of annotations alongside a PHP class. Now Drupal supports and recommends the use of PHP attributes instead. During the transition, most developers will still need to know how to recognize and implement annotation-based plugins.
In this tutorial we'll:
- Provide a recipe for implementing annotation-based plugins.
- Demonstrate how to figure out where the code and metadata should live for annotation-based plugins.
By the end of this tutorial you should have a recipe for getting started with implementing annotation-based plugins, and a better understanding of how to figure out the details required to implement a given plugin type.
Many of Drupal's APIs that look like a bunch of configuration in a YAML file (migrations, menu links, etc.) are actually plugins in disguise. The YAML from these files is used as arguments to a generic PHP plugin class which then behaves differently depending on the provided values. As a developer, you probably don't need to know that menu links are plugins, but it can be helpful when debugging or just trying to get a better understanding of the big picture.
In this tutorial, we'll:
- Learn about how YAML-based plugins work
- Discuss how to find the implementation details for YAML-based plugins
- Walk through an example of implementing a YAML-based plugin
By the end of this tutorial, you should be able to recognize a YAML-based plugin definition, and author your own.
In Drupal's Appearance UI, all themes get a theme settings form. As a theme developer, you can customize the theme settings form, enabling site administrators to have more control over the appearance of the theme.
In this tutorial, we'll show you how to add admin-configurable settings to your theme. In the process of doing this, we'll use a variety of theme and module development skills and assume you have some familiarity with using Drupal's Form API, Configuration API, and theme system (see Prerequisites).
By the end of this tutorial, you will be able to provide custom theme settings that an administrator can use to modify the appearance of the theme.
Any text that will be displayed to user as part of your application's user interface should be passed through the t()
function, or an equivalent, so that it can be translated into other languages as needed. This tutorial will look at how to use the t()
function.
This tutorial contains information that applies to anyone writing modules or themes. And many of the tutorials you read on this site and on the web in general will expect that you understand how basic string translation works.
In this tutorial we'll look at:
- Passing strings through the
t()
function or equivalent so they are available for translation - Using placeholders for dynamic content in translatable strings
- Tips for making your code's interface strings easier to translate
Before you can create a path or link to another page on your site, you'll need to know the route (unless there is already a variable available for the URL you need). Finding a route can be a tricky task unless you have the right tools. In this tutorial, we'll show how tools like Webprofiler, Drush, and Grep can be used to get route information for a page, so that you can use functions that need a route as a function parameter.
In this tutorial we'll:
- Learn how to determine the route or path of an internal page.
In this tutorial, you'll learn how to add a property to a configuration entity in Drupal. Previously, we created a configuration entity called Transcode Profile and learned about the files and code that compose a configuration entity. Now, we'll add a new property called codec to this configuration entity and learn some new concepts in the process.
In order to add this new property to our custom configuration entity, we'll need to update our schema file, configuration entity forms, the entity list builder class, and add getter and setter methods to our main TranscodeProfile
class.
In this tutorial, you'll learn about the two types of configuration data: simple configuration and configuration entities. By the end of this tutorial, you should have a better understanding of which type of configuration to use in your module.
In this tutorial we’re going to walk through the process of creating a custom configuration entity in Drupal in a custom module. We'll be using Drupal Console's generate:entity:config
command to create and update the files in our Transcode Profile example module. After Drupal Console has generated and updated the files for our configuration entity, we'll walk through each file and see how they define data structure, metadata, an administrative interface, and menu links for a configuration entity in Drupal.
By the end of this tutorial, you should be able to:
- Use Drupal Console to generate a configuration entity
- Identify files associated with a configuration entity and summarize the purpose and function of the code inside each file
- Find other examples of configuration entities in Drupal core
As a developer, within a module, you can define settings for the module and provide a configuration form for administrators to update the values of those settings. In this tutorial, we'll create a configuration settings form for a module and define default values for each setting. We'll use Drupal Console, a command-line utility for Drupal to do some code scaffolding and speed up the process.
By the end of this lesson, you should be able to get a basic settings form up and running inside a custom module complete with default settings and a menu link.
As we learned in Configuration Data Types, simple configuration is suitable for storing module settings as boolean values, integers, or text strings in one or more key/value pairs. In this tutorial, we'll walk through creating a schema and providing default configuration to store initial settings that a module needs to function.
Not every environment or copy of a site you may be working on will be created equally. You may want to enable logging on a development site or need to use different API keys depending on the environment. But you also need to make sure that your instance-specific configuration overrides don't make it into the database, mistakenly get exported, or compromise security.
In this tutorial, you will learn how to:
- Override the global
$config
array in settings.php (or settings.local.php) - Retrieve overridden (immutable) configuration (read-only mode)
- Retrieve original (mutable) configuration for updating (read/write mode)
- Set dynamic values for configuration instead of overriding values
When you create a module for Drupal, it can be useful to provide default configuration. This can be settings for a form, the placement of a block, or something more complex like the default image styles provided by the Image module in core. A module can provide default configuration for simple configuration or configuration entities.
In this tutorial, we will cover:
- Possible locations for default configuration
- What happens with configuration when a module is installed or uninstalled
- Managing dependencies in configuration
- Where to find examples of default configuration
Configuration entities are suitable for creating user-defined configuration, such as image styles, views, content types, etc. A configuration entity type is defined by a module, default configuration is provided by that module as well as any other module, and then users can create zero or more configuration entities through Drupal's administrative UI.
In this tutorial, you will learn about:
- What configuration entities are
- Configuration entity types versus configuration entities
- An example in core: image style
- Overview of the process of creating your own configuration entity types in a module
When working on configuration in a module, whether as part of a migration that uses Migrate Plus configuration entities, or while developing custom configuration entities, you'll often need to re-import the configuration stored in the .yml files of the modules config/install/ or config/optional/ directories. This is tricky though, because Drupal only reads in those default configuration settings when the module is first enabled. So any changes you make to those files after the module has been installed will not be reflected without these workarounds.
Knowing how to do this can improve the developer experience of adding (or debugging) the default configuration that's provided with a module. Or for anyone using Migrate Plus configuration entities as part of a migration.
In this tutorial we'll:
- Learn about the Configuration Development module
- Look at how you can use Drush to perform a partial configuration import
- Write an implementation of
hook_uninstall()
to remove a module's configuration when it's uninstalled
By the end of this tutorial you should be able to re-import the configuration provided by a module without having to uninstall and then reinstall the module.
Now that we have some default simple configuration stored in a settings YAML file, let's utilize it in a form that our site administrators can use to update those values. We'll make use of some services and methods in Drupal's Configuration API in order to retrieve, update, and save simple configuration values with a form.
In this tutorial, we'll cover how to load configuration entity data in a module. We'll change the AdminSettingsForm.php we created and replace the simple textfield we were using with a dropdown select list. Then we'll use data from our Transcode Profile module's configuration entity, loaded by the EntityTypeManager
via the services container, to choose our preferred Transcode Profile.
By the end of this tutorial, you should be able to:
- Know how to load configuration entities using
EntityTypeManager
via the services container - Update the AdminSettingsForm.php to use a dropdown select list
- Save your preferred transcode profile from a list of transcode profile entities
- Update the default configuration provided with the demo module to include transcode profiles
Containers are sandboxed applications that can be run anywhere, no matter the underlying host OS. Docker containers are quite different from VMs in a number of ways that need to be understood before we can use them to develop Drupal sites.
In this tutorial, we'll:
- Define a container
- Explain how a container is a more limited environment than a VM