I’ve spent a lot of time thinking about why learning Drupal is hard over the past 10 years and how we can lower the barrier by providing the right types of resources at the right time. This has led to the creation of things like the first-time contributor workshops at DrupalCon, the Drupal User Guide, and, of course, the library of content at Drupalize.Me.
What Drupal really needs right now is a curated, well-organized, and highly polished “Hello world” guide for developers. Something like React’s Quick Start, or Django’s writing your first Django app. A guide that you can work through in order, and by the end, you’ve created a real application with custom code you wrote, like the to-do list app so many of us created to learn PHP in the first place.
Image generated by OpenAI's DALL-E, a deep learning model specializing in image creation, 2023. Depicts a storybook-style illustration representing the programming concept 'Hello, World!' with the Drupal logo.
Creating more hands-on learning resources
For a long time, one of our goals at Drupalize.Me has been to create a deep library of reference-quality documentation. Tutorials we could point someone to and say, “If you want to know more about how X works, go here.” And “here” should be thorough, complete, and up-to-date.
Some of this is new content we create on Drupalize.Me, and some is content we help curate on Drupal.org. The idea is that once that is in place, we can create more hands-on guides, or recipes, for real-world scenarios. In those guides we could focus on the task at hand without having to get too deep into the weeds because we could point you to another page that has the nitty-gritty details – if that’s what you want.
For example, I want to be able to say things like; “Next, create a block plugin that outputs the content ‘Hello @name’ to the page” and then show some example code that does that. You can copy/paste the code and it’ll work, but that example code is making a whole lot of assumptions:
- You know what blocks are.
- You know what plugins are.
- You know what services are.
- You can use dependency injection to insert a service into a plugin class.
- You know what cache context and tags are and how to set them on a renderable array.
- You know what a render array is.
- ...and probably more.
Or to be able to do things like create a link to a route without explaining routing and rendering.
Sometimes all those prerequisites can get in the way of learning. Maybe it’s okay to just copy/paste the part of the code that deals with caching for now because that’s not the part we’re focused on. But, if you want to know more you should be able to click-through and dig in.
And while there’s always more reference documentation we can add, we feel like our current content is sufficiently deep to start creating some more high-level guided walk-throughs.
A quick-start guide for developers new to Drupal
Years ago I was involved with authoring the Drupal User Guide, and I’m still the maintainer today. The User Guide offers this kind of a learning path for Drupal site builders.
Now, we want to pick up where the Drupal User Guide left off, and create a Drupal Module Developer Guide. This hands-on module developer guide will build on the site and the guiding scenario used for the User Guide. We’ll walk through the process of authoring a couple of custom modules to meet your client’s needs and in the process, learn the basics of Drupal module development through writing “real-world” code.
The Drupal Module Developer Guide is going to make a bunch of assumptions like familiarity with PHP and Drupal site building. Maybe you’ve had some experience building sites with other frameworks. You’re comfortable with the command line, and the features of your IDE. Basically, this guide isn’t for someone new to development. It’s for a developer who is new to Drupal.
It’s still very much a work in progress, but it’s what I’ve been spending most of my time on this past month. And I’m supposed to blog about what I’ve been working on. 🙂
Below is the current working outline for the guide, and over the next few months we’ll be writing example code, drafting tutorials, and recording videos to fill out this outline.
If you’ve got any thoughts on this outline I would love to hear them. Leave a comment, or send me an email: [email protected].
-
Preface
- Audience & Goal
- Organization
- Guiding Scenario
- Prerequisites - e.g. OOP PHP / CLI / etc.
- Recommended prereq: Drupal User Guide Chapters 1-9 (You should be familiar with Drupal as a site building tool before you attempt to build a module.)
-
Chapter: Introduction to Drupal Module Development
- Concept: What are modules? - Extend, Alter, and Enhance Drupal
- Concept: How Drupal Handles a Page Request (request → routing → controller → view → response)
- Concept: Documentation for developers (api.drupal.org, drupal.org/project/examples, etc.)
- Concept: Development environment - use DDEV - link to quickstart guide?
- Concept: Tools for module developers (drush, devel, phpstan, xdebug, etc.)
- Task: Setup DDEV and Build the Initial Site - link to user guide content
- Task: Install Drush & Devel (assume people are starting from a complete version of the user guide site)
-
Chapter: Hello world
- Focus more on copy/paste this code and you’ll get something that works, come back and explain the details later.
- Concept: Where does your custom code go and what should you name it?
- Concept: Info files
- Task: Create a .info.yml file
- Task: Create a custom block (Just get something simple on the page - Block plugin - “Hello world block”)
- Task: Enable your custom module
-
Chapter: Routes and Controllers
- Concept: Routing
- Concept: PHP Namespaces and PSR-4
- Concept: Controllers
- Task: Create a new route
- Task: Create a controller
- Task: Add a parameter to the route
- Concept: Menu Items and Links
- Task: Define a Menu Item
- Concept: Permissions
- Task: Define a new permission
-
Chapter: Services & Dependency Injection
- Concept: What are services?
- Concept: Dependency Injection
- Task: Locate Existing Services and their Documentation
- Task: Use a Service In a Controller
- Task: Define a Service -
¯\*(ツ)*/¯
- make sure the new service depends on another service to show how to chain them in services.yml - (maybe) Concept: Custom Services
- (maybe) Concept: Third Party Libraries via Composer
- (maybe) Task: Add A composer.json File — Maybe something with a 3rd party composer library?
-
Chapter: Outputting Themable Content from a Module
- Concept: Themable output
- Concept: Render API
- Task: Define Content Using Render API
- Concept: Template Files
- Task: Add a template file (for our page)
- Task: Add a preprocess function
- Concept: Asset Libraries
- Task: Add CSS/JavaScript to the page
- Concept: Localization (i18n)
- Task: Use t() to output strings
-
Chapter: Hooks and Events
- Concept: What are Hooks?
- Concept: What are Events?
- Task: Locate hooks and their documentation (see what hooks are invoked when)
- Task: Implement
hook_help()
- Task: Invoke a Custom Hook
-
Chapter: Plugins
- Concept: What are Plugins?
- Task: Implement a Plugin (Revisit the block example from hello world and explain it from the lens of plugins?)
- Task: Use a Service in a Plugin
-
Chapter: Forms
- Concept: Form API
- Concept: Form Controllers
- Task: Create a Settings Form (location to use for looking up weather)
- Task: Validate User Input
- Task: Handle Submitted Data (save as config)
- Concept: Alter Existing Forms
- Task: Add a terms of service checkbox to user reg form and require it gets checked
-
Chapter: Working with Data
- Concept: Types of Data - Config vs. Content vs. State
- Concept: Configuration Management
- Task: Use Custom Configuration Data (pull location setting into weather checker service)
- Task: Define a Configuration Schema & Defaults
- Concept: Entities for Data Storage
- Concept: Fieldable Entities
- Task: Setup required … set up the new field(s) on vendor content type, and create a new module skeleton.
- Task: Create a Form For Editing An Entity (dynamic routing like vendor/{node.id}/status)
- Task: Read an Entity’s Field Values
- Task: Update An Entity
- Task: Use parameter upcasting for entities in routes
- Task: Entity Validation - Validate Username
- Concept: Query Entities with EntityTypeManager
- Task: Create a Page Showing Summary of Vendor Statuses
- Task: Implement a cron task to reset vendor attending status
- Concept: Custom Entity Types (why, when, link to how)
-
Chapter: Caching
- Concept: Caching
- Task: Cache Data Retrieved from Weather API
- Task: Add Cache Context and Tags to Render Arrays
-
Chapter: Testing
- Concept: Types of Tests in Drupal
- Task: Run a Test Suite
- Task: (Write a unit or kernel test)
- Task: (Write a functional test)
-
Chapter: Additional considerations
- Concept: Security
- Concept: Coding Standards
- Task: Lint Your Code with phpcs
- Concept: Update Hooks
- Task: Implement hook_update_N() to modify existing data
-
Chapter: Collaborate with the community
- There’s a module that does most of what I need but it needs some updates, or tweaks, how can we help with that instead of writing a custom one?
- Concept: Contribution and Collaboration
- Task: Publish Your Custom Module on Drupal.org
- Task: Fix a Bug in an Existing Contributed Module
-
Chapter: Final Thoughts
- Learning More
- Getting Support
- Index
Add new comment