Drupal's performance story depends almost entirely on caching. A Drupal site without caching tuned correctly will struggle to serve a few dozen concurrent users. The same site with all three cache layers configured properly can handle hundreds. The three layers — Drupal's internal cache, Redis as a cache backend, and Varnish as a reverse proxy cache — serve different purposes and work together. This article explains what each layer does, how to configure it, and how to diagnose problems when the layers interact unexpectedly.
PHP 8.1 introduced enums as a first-class language feature. After a few years in the wild they are well-supported across frameworks, Drupal, and static analysis tools — but many PHP developers still use constants or pseudo-enum classes out of habit. This article covers everything you need to use enums effectively: pure enums, backed enums, methods on enums, interface implementation, and the patterns that emerge when you integrate enums into domain models, Drupal fields, and API responses.
Running Drupal locally with a Docker Compose stack gives you a reproducible environment that matches production. Every team member gets the same PHP version, the same MariaDB version, and the same Nginx configuration — no more "works on my machine" debugging sessions. This guide builds a complete, production-mirroring stack from scratch: Nginx as the web server, PHP-FPM for request processing, MariaDB for the database, and optional Redis for caching.
The result is a stack you understand completely, unlike opaque tools that hide the configuration from you.
Emacs has two mature LSP clients: Eglot, which ships with Emacs 29+ as a built-in package, and lsp-mode, a third-party package with a far larger feature surface. Choosing between them is not just a matter of features — it is a decision about how much configuration complexity you want to carry, what your workflow actually demands, and whether you are optimising for responsiveness or for capability.
This article compares both in detail, with specific guidance for PHP and Drupal development where both are viable choices.
For years Drupal used docblock annotations — special comments parsed at runtime by the Doctrine Annotations library — to declare plugins, entity types, and field formatters. PHP 8.0 introduced native attributes as a first-class language feature, and Drupal 11 now supports them everywhere annotations were used. Drupal 11.1 went further, making PHP attributes the preferred mechanism and marking the annotations approach for eventual deprecation.
Every Drupal project eventually needs custom code. Whether it is a new content type with business logic, a custom REST endpoint, or a block that pulls data from an external API — the answer is a custom module. This guide walks through building a complete Drupal 11 module from scratch: the required file structure, routing, a controller, a service, a custom block, and hooks implemented with the PHP attribute syntax introduced in Drupal 11.
All examples use PHP 8.3+, Drupal 11 conventions, and the web/ Composer project layout.
Property hooks are the headline feature of PHP 8.4. They let you attach get and set logic directly to a property declaration, removing the need for hand-written getter and setter methods in many common situations. IDEs and static analysis tools understand them natively — unlike magic __get/__set pairs, which are effectively invisible to tooling.
In a previous article I covered getting GPTel running with LM Studio and a local Qwen model — a great setup when privacy and offline access matter. But the Emacs AI ecosystem has grown considerably, and there is now a whole family of packages targeting different parts of a coding workflow.
Running a Drupal site on Nginx means you are responsible for your own security posture. The default Nginx configuration is permissive — it is built for compatibility, not hardening. This guide walks through every layer of a production-grade Nginx configuration for PHP and Drupal sites: from hiding server fingerprints and locking down sensitive files, to security headers, TLS hardening, rate limiting, and PHP-FPM settings.
All examples are tested against Nginx 1.24+ and Drupal 10/11. Adapt paths to match your server layout.