
The term web services has been around for quite a while. Given that web services is such a broad topic, let's define what web services are and how we are going to refer to them throughout this series so we are all on the same page.
This tutorial is an introduction to web services that will help you:
- Learn what a web service is.
- Understand that this series focuses on HTTP web services, and mostly on REST principles.
- Get some examples of APIs in the wild and what type of consumers they have.
By the end of this tutorial, you'll be able to define what web services are, and how we'll use the term in the context of these tutorials.
When running migrations you can use the highwater_mark
source plugin configuration option to influence which rows are considered for import on subsequent migration runs. This allows you to do things like only look at new rows added to a large dataset. Or to reimport records that have changed since the last time the migration was run. The term, highwater mark, comes from water line marks found on structures in areas where water level changes are common. In running migrations, you can think of a highwater mark as a line that denotes how far the migration has progressed, and saying, "from now one, we only care about data created after this line".
Another common use case for highwater marks is when you're importing a large dataset and the system runs out of resources. Usually this will look like a migration failing because it timed out, or the process ran out of memory. A highwater mark should allow you to pickup from where you left off.
In this tutorial we'll:
- Define what a highwater mark is, and how you can use them to limit the rows considered for importing each time a migration is executed.
- Demonstrate how highwater marks can be used to reimport source records that have been modified since the previous time the migration was executed.
- Introduce the
track_changes
option.
By the end of this tutorial you should be able to define what a highwater_mark
is and how to use them to speed up the import of large datasets or force the migration to reimport records when the source data is changed.
You should also be aware of the track_changes
feature which is a slower, but more dynamic, method of checking for changes in source data and reimporting records when a change is found.
If you need to write a migration that is capable of being executed multiple times and picking up changes to previously imported data, you can use the track_changes
configuration option of most source plugins. This will tell the migration to keep a hash of each source row, and on subsequent runs of the same migration it will compare the previous hash to the current one. If they don't match this means the source data has changed, and Drupal will reimport that record and update the existing destination record with new data.
Using track_changes
differs from calling drush migrate:import --update
in that using --update
will force every record to be re-imported regardless of whether the source data has changed or not.
In this tutorial we'll:
- Learn how change tracking works to detect changes in your source data
- Use the
track_changes
option in a migration
Note that progress of a migration can also be tracked using highwater marks if the source data has something like a last_updated
timestamp column. Using highwater marks in this case is likely more efficient than using track_changes
. It's a good idea to understand how both features work, and then choose the appropriate one for each migration.
Before you can migrate your Drupal 7 site to the latest version of Drupal you'll need to be able to build the features that make up the current site. Part of this is evaluating all the modules you've got installed, figuring out what you're using them for, and if there's a version that's compatible with the latest version of Drupal along with a migration path.
I usually make a spreadsheet for this. But any list of the modules you’re currently using that allows you to keep track of how you plan to update them will work. You also want to keep track of where you are in the process of figuring that all out. Because it’s likely you’ll have some modules for which the path is clear, and others where it’s pretty murky and requires more in-depth research to find a path forward. Having a list means you can break that up into tasks, and ensure you’re not missing something. It'll also help you define when your migration is done as well as any final quality assurance (QA) tasks.
In this tutorial we'll:
- Start a list of the modules that make up our current site.
- Point to some tools that can help speed up the process of evaluating a module's readiness.
- Provide a set of questions that you can ask about each module you're using as part of your planning process.
By the end of this tutorial you should have a list of all the modules you're currently using, and some tools you can use to help you figure out how to move forward with each one.
If you want to be able to say you're done with your Drupal-to-Drupal migration, first you have to be able to define "done". And part of that is doing a content analysis and inventory. Performing a content analysis and inventory will help you ensure that you don't miss any fields or important records. It also gives you an opportunity to spend some time thinking about the overall information architecture of your site. You're already going to be doing a lot of work to migrate your content, so deciding to shuffle things a bit now might not add any significant extra time. Additionally, the latest Drupal (as of Drupal 10) is a different platform than either Drupal 6 or 7, and as such, there are some new best practices and new ways of doing things that might not have been available before.
In this tutorial we'll:
- Provide a set of questions you can ask yourself about the content of your current site to kick-start your analysis.
- Give an example of how we create a content type inventory in a spreadsheet and use that to help define "done" for our projects.
By the end of this tutorial you should be able to get started analyzing the content and content types of your existing site in order to start planning for your Drupal-to-Drupal migration.
Because current versions of Drupal are so much different from older versions like Drupal 7 upgrading to the latest version requires creating a new site using the latest version of Drupal and then migrating your old site's content and configuration into it.
There is no one right way to tackle a Drupal-to-Drupal migration. Instead, it's like walking down a path and coming to a fork in the trail and then choosing a direction over and over and over. Since every site is different, every path to a finished migration will be different, too. I know nobody wants to hear it, but every migration is its own unique adventure. Every successful migration will require its own custom code, weird shell scripts, and detailed lists of the exact order of things. But that doesn't mean there's no plan to follow.
A successful migration charts a course through the maze, while leveraging existing tools and experience to help find the shortest route and the right path at each fork--with minimal backtracking due to wrong choices.
In this tutorial we'll:
- Look at what makes a Drupal-to-Drupal migration (a major version upgrade) so tricky, and how to think about performing one
- Define 3 high-level approaches to performing a Drupal-to-Drupal migration
- Get a better idea of what the migration work entails, so you go into it with a proper mental model.
By the end of this tutorial you should be able to explain the different approaches to performing a Drupal-to-Drupal migration in broad strokes, and have a better picture of the work that will be involved.
The migration_lookup
process plugin allows you to populate entity reference fields when the entity that you want to reference is created by another migration, and you don't yet know what the unique ID will be in the Drupal database. Think of this as being able to answer the question: I have a migration that imports new users from a CSV file, and another that imports articles from a different CSV file. The articles' CSV file has a column that indicates which row from the users' CSV file is the author of this file. But in order to populate the author field for the Drupal node I need to know the ID of the imported user which is an auto-incremented ID that I'm not setting. So, what is the correct ID to use?
Another use case is circular dependencies, like hierarchical taxonomies with parent/child relationships. Or a content type with a field that references other nodes of the same type, like articles that reference other articles.
In this tutorial we'll:
- Learn about the
migration_lookup
process plugin and its configuration - Provide examples of using the plugin to populate entity reference fields during a migration
- Look at alternatives
By the end of this tutorial you should be able to use the migration_lookup
plugin to effectively manage entity relationships across multiple individual migrations.
When a migration is run the Migrate API creates a mapping table that keeps track of what source record was used to create which destination record. A record is automatically added for each successfully migrated row. This mapping table can be used later to:
- See if a row was previously imported
- Look up the ID of the entity created for the row
- Tracking if a source record has changed and needs to be re-imported.
In this tutorial we'll learn:
- What migration map tables are
- Why they exist, and what the Migrate API does with them
By the end of this tutorial you should be able to explain the use case for map tables and describe the data they contain.
Do you know some PHP and want to learn how to create a custom page at a custom URL in Drupal? You're in the right place.
Every web framework has the same job: provide a way for developers to map user-accessible URLs with code that builds the page. Routes, controllers, and responses are what module developers use to create pages at custom URLs in a Drupal site.
In this tutorial, we'll:
- Define what routes, controllers, and responses are.
- Explain the routing workflow that Drupal uses to match a URL to a route.
- Define routing system-related terms like parameter and upcasting.
By the end of this tutorial, you should be able to explain how a developer uses routes, controllers, and responses to create custom pages in a module.
If you want to define a new URL that a user can navigate to, and custom PHP code that will generate the content of the page, you need a route and a controller. Most of the time you'll want to do something more complex than hard code the content of the page. This will require using services in your controller. This can be accomplished in different ways.
In this tutorial we'll:
- Provide the definition for a new route which maps a path to the callback method of a controller class.
- Create a controller that returns a hard coded string.
- Look at examples of using both
ControllerBase
and dependency injection to access services from a controller, and discuss the benefits of both approaches.
By the end of this tutorial, you should be able to define a new route that maps to a controller and displays content on the page as a result of your custom logic.
Want to know if the person that's viewing your custom block is authenticated? Need to change the elements visible on the page based on a user's permissions or roles? Want to display a welcome message for users returning to your site?
All of these things require knowing who the user is that's currently accessing a page. This can be accomplished by using the current_user
service to load an object that contains information about the current user as well as methods for checking permissions, and retrieving additional information.
In this tutorial we'll:
- Define what "current user" means
- Use the
current_user
service to retrieve an implementation of\Drupal\Core\Session\AccountInterface
- Retrieve information about, and check the permissions of, the current user
By the end of this tutorial you should be able to retrieve and make use of information about the applications current user in order to perform logic in your code that customizes the response for different users.
React is a JavaScript library that makes it easy to create interactive user interfaces. Drupal is a content management system with a powerful web services API. React and Drupal can work together in a couple of different ways. This series of tutorials explores some of those options, and the related concepts and terminology.
Our goal is to provide you with some baseline information you can use to get started integrating React and Drupal together. After you've completed these tutorials you should be able to better envision how to use these two technologies to solve some of your own issues. We hope you'll come away from this with enough knowledge to start exploring further on your own. We link to external resources liberally, and encourage you to explore beyond the examples we provide, read the linked resource, and dig in. There's no substitute for exploration and experimenting with real code when it comes to learning these things.
In this series we'll:
- Introduce the technical side of React, terminology, and information about where to find more resources
- Learn about using Drupal, and the JSON:API module, to turn Drupal into a powerful web services API provider
- Learn about the use cases for adding React to a Drupal site
- Walk through increasingly complex code examples that start with a "Hello World!" application, and end with a fully decoupled application that can list, create, update, and delete content in Drupal
- Learn about how to authenticate a Drupal user via an API using React
- Contrast, through example code and use cases, the differences between integrating React into an existing Drupal theme or module and creating a stand-alone React application
- And more!
Before we start writing any React code, let's go over some basic concepts and terminology. Throughout this series we'll assume you're familiar with these things. They'll come up again and again as you work on projects that involve React, so it's worth taking the time to learn them.
In this tutorial we'll cover the following at a high level, and provide links to resources:
- Why choose React?
- What are React components?
- What are hooks, state, and JSX?
- The role of build tools when developing React applications
By the end of this tutorial you should have a firm grasp of the fundamental concepts and terminology necessary to start creating React applications.
React and Drupal can be used together in two different ways: fully decoupled, also known as headless; or progressively decoupled.
In this tutorial we'll talk about the differences between these two approaches, including:
- Defining what each method refers to
- Considerations regarding hosting, performance, and access
Then we'll link to lots of additional reading materials so you can gain a deeper understanding of the subject.
By the end of this tutorial you should be able to define what decoupled and progressively decoupled mean, and how they differ from one another.
Writing a React application requires including the React JavaScript library in the page, writing some React-specific JavaScript, and then binding it to a specific DOM element on the page. You may also want to include existing packages from the npm ecosystem, and use modern JavaScript (ES6+) features, which necessitates setting up a build toolchain for your JavaScript using a tool like Webpack or Parcel.
There are a lot of different ways you could go about setting this all up. Do you add React via a theme or a module? Do you need a build tool? Should you use Webpack, or Babel, or Parcel, or something else? While we can't possibly cover all the different approaches, we can help you figure out what is required, and you can adapt our suggestions to meet your needs.
In this tutorial we'll:
- Create a new custom theme with the required build tools to develop React applications
- Add a DOM element for our React application to bind to
- Create a "Hello, World" React component to verify everything is working
By the end of this tutorial you'll know how to configure everything necessary to start writing React within a Drupal theme.
Components are the fundamental building blocks of any React application. React uses components to represent different elements in the UI. To show this, we'll build a React widget that can query the Drupal.org REST API to retrieve usage statistics for a project and then display them. We'll create buttons that allow us to toggle between two different projects. In doing so we'll learn about creating components and using props and state in React.
In this tutorial we'll:
- Define two new React components
- Learn about using props to pass data to a component
- Learn about using state, and the
useState()
hook, to create interactivity
By the end of this tutorial you should have a basic understanding of how to write a React component that uses props and state to display data from a third party API.
React excels at displaying lists of data. But that data needs to come from somewhere. In most cases this happens by making a network request to retrieve data from one or more APIs, processing the response, and then displaying the data. In the context of working with a Drupal site there are two possible options: Drupal core's JSON API module, or the drupalSettings
JavaScript API.
In this tutorial we'll focus on the high-level overview and:
- Explain the difference between content and configuration data
- Introduce the JavaScript Fetch API, and where to find information about using it
- Get an overview of the ES6 array functions we'll use to parse the complex data structures returned from an API
In the remaining tutorials in this series we'll provide examples of real world use cases.
By the end of this tutorial you should have a firm understanding of how to get started making API requests using React.
In order for our React code to list content from Drupal we'll need to enable the Drupal core JSON:API module, and then use fetch()
in our React component to retrieve the desired data. This technique works for both React code embedded in a Drupal theme or module, and React code that is part of a fully decoupled application. We'll discuss the differences between those styles as well.
In this tutorial we'll:
- Use
fetch()
to bring data from Drupal into React - Parse the data using ES6 array functions to find just the bits of data we need
- Combine multiple React components together to render a list of articles retrieved from Drupal
By the end of this tutorial, you should have a better understanding of how data from a Drupal API gets incorporated into a React application.
To perform create, update, and delete (CRUD) operations with Drupal core's JSON:API via React there are a few things you'll need to understand. First, how to format the POST
, PATCH
, and DELETE
requests necessary to add, edit, and delete Drupal entities. Next, how to handle authentication, and cross-site request forgery (CSRF) tokens. Over the next few tutorials we will create a simple but powerful React application that can add, edit, and delete Drupal node content.
This tutorial contains:
- An overview of the application we're building
- Information about making secure authenticated requests to Drupal's JSON:API
- An overview of the API requests we'll use to create, update, and delete nodes
By the end of this tutorial, you should have a picture of the application we're going to build, and know how to make the API requests we'll use in our application.
Using React we can do more than just list content. By using the POST, PATCH, and PUT methods of Drupal core's JSON:API web service we can also add, update, and delete, content entities. To demonstrate how this works we'll create a small React application with a form that lets you add, edit, and delete article nodes.
In this tutorial we'll:
- Learn how to handle user authentication and CSRF tokens in a React application
- Create a single React component that outputs a form to add or edit content
- Create a wrapper around the JavaScript
fetch
API to assist in dealing with requests to Drupal's JSON:API
By the end of this tutorial you should know how to create, edit, and delete content in a Drupal site using a React application.