Symfony 5.4 LTS: enum support, route aliases, and the PHP 8.1 bridge

Symfony 5.4 landed November 29, 2021, same day as Symfony 6.0 and one day after PHP 8.1 was released. Not a coincidence. 5.4 is the LTS, and its job is to carry as much of 6.0’s feature set as possible while keeping 5.x compatibility intact. It’s also the first Symfony release that actually understands PHP 8.1 features. Enum support PHP 8.1 introduced native enums. Symfony 5.4 embraces them immediately: enum Status: string { case Active = 'active'; case Inactive = 'inactive'; } The EnumType form type renders enums as select fields, no custom transformers needed. The validator understands backed enums. The serializer maps enum values to their backing type and back. Three components updated in one shot, which meant migrating codebases from pseudo-enum constants to real PHP 8.1 enums was actually pretty smooth. ...

January 10, 2022 · 7 min · Guillaume Delré

PHP 8.1: enums, fibers, and the type system growing up

PHP 8.1 released November 25th. It follows 8.0’s sweeping overhaul with something different: fewer features, but each one thought through rather than bolted on. Enums This is the one that changes codebases the moment you upgrade. Before 8.1, PHP enumerations were either class constants, strings, or integers with nothing enforcing them: // before: nothing stops Status::INVALID from being passed const ACTIVE = 'active'; const INACTIVE = 'inactive'; // after enum Status: string { case Active = 'active'; case Inactive = 'inactive'; } function activate(Status $status): void { ... } PHP enums are objects, not scalars. They support methods, interfaces, and constants. Backed enums (with a string or int value) serialize cleanly and map to database columns naturally. Pure enums (no backing type) enforce domain concepts without worrying about serialization. ...

January 9, 2022 · 5 min · Guillaume Delré

PHP 8.0: match, named arguments, attributes, and JIT

PHP 8.0 shipped November 26th. I’ve been running it for six weeks on a side project and a greenfield service at work. It’s the most significant PHP release since 7.0, and in some ways more impactful, because the changes pile on top of each other in useful ways. JIT The Just-In-Time compiler was the headline announcement. The reality in production is more nuanced: for typical web apps (database queries, HTTP calls, template rendering) the gains are modest, because those workloads are I/O bound, not compute bound. Where JIT actually shines is CPU-intensive code: image manipulation, data transformation, mathematical computation. ...

January 10, 2021 · 8 min · Guillaume Delré

Revision pruning with window functions and logarithms, when DQL wasn't enough

Every content update on the platform creates a revision. That’s by design: editors need a history they can roll back to, and the platform needs an audit trail. What nobody anticipated was the rate. Some articles go through forty saves in a single afternoon. A high-traffic piece accumulates hundreds of revisions over its lifetime. After a few months, the revision table had several million rows. Deleting them naively wasn’t an option. “Keep the last 50” loses all historical context for articles that haven’t been touched in a year. “Keep one per day” loses all the detail for content that’s actively being edited. What we needed was a distribution that matched how revisions are actually used: dense coverage for recent history, sparse coverage for old history. ...

September 27, 2020 · 8 min · Guillaume Delré

PHP 7.4: typed properties and the arrow function you actually want

PHP 7.4 landed November 28th. It’s the last 7.x release before PHP 8.0, and it feels like it. The features are substantial enough to stand on their own, but they also read as groundwork for what’s coming. Typed properties This is the one. Since PHP 7.0, you could type function parameters and return values. But class properties? Still untyped: class User { public int $id; public string $name; public ?DateTimeInterface $deletedAt; } 7.4 changes that. Typed properties enforce types at assignment, not just at call sites. Classes become self-documenting in a way that docblocks never quite managed, and the engine catches type errors before they propagate through half your stack. ...

January 12, 2020 · 6 min · Guillaume Delré

Symfony 5.0: String, Notifier, and the secrets vault

Symfony 5.0 released November 21, 2019, same day as 4.4. Where 4.4 is about stability and a long support window, 5.0 is the next chapter: no deprecated code, PHP 7.2.5 minimum, and a handful of new components that finally address gaps that had piled up for years. The String component PHP’s string handling is famously scattered: prefix-style functions here (str_), suffix-style there (strpos), inconsistent encoding support, and nothing object-oriented in sight. The String component wraps all of this into a fluent, unicode-aware object API: ...

January 6, 2020 · 5 min · Guillaume Delré

Symfony 4.4 LTS: HttpClient, Mailer, Messenger, and the features that stayed

Symfony 4.4 and 5.0 both landed November 21, 2019. 4.4 is the LTS: same feature set as 5.0, deprecation layer baked in, and a long support window for teams that can’t follow every release. The feature worth singling out arrived in 4.2 and matured through 4.3 and 4.4: HttpClient. HttpClient PHP’s built-in HTTP options (file_get_contents with stream contexts, cURL, Guzzle) each have their own model, their own quirks, and their own abstraction cost. Symfony 4.2 introduced HttpClient, a first-party HTTP client with one API over multiple transports. ...

January 4, 2020 · 7 min · Guillaume Delré

PHP 7.3: small wins that add up

PHP 7.3 shipped December 6th. No single killer feature. It’s a collection of quality-of-life improvements that individually feel minor but together make daily work noticeably less annoying. Flexible heredoc and nowdoc Until 7.3, the closing marker of a heredoc had to be at column zero. That forced awkward de-indentation in otherwise well-formatted code: // before $html = <<<HTML <div> <p>Hello</p> </div> HTML; // had to be at column 0, ugly // after $html = <<<HTML <div> <p>Hello</p> </div> HTML; The closing marker can now be indented to match the surrounding code, and that indentation is stripped from the content. This looks cosmetic. It’s not. Heredocs in nested contexts (class methods, conditionals) were visually jarring before. Now they fit. ...

January 20, 2019 · 6 min · Guillaume Delré

PHP 7.2: goodbye mcrypt, hello sodium

PHP 7.2 released November 30th. The headline isn’t a language feature, it’s a removal. mcrypt is gone. This is good news, even if it doesn’t feel that way when you’re the one migrating. The mcrypt problem mcrypt has been unmaintained since 2007. More than a decade of stagnation in a cryptography library. It was deprecated in 7.1, and 7.2 removes it entirely. The replacement is sodium, now bundled as a core extension. ...

January 14, 2018 · 6 min · Guillaume Delré

Symfony 4.0: Flex and the end of the Standard Edition

Symfony 4.0 released November 30, 2017, same day as 3.4. The shared release date is pretty much the only thing they have in common. 4.0 is a different philosophy. The Symfony Standard Edition, the monolithic starting point that bundled everything and left you to remove what you didn’t need, is gone. In its place: a microframework that grows. Flex Symfony Flex is a Composer plugin that changes how you install Symfony packages. Before Flex, adding a bundle meant: install via Composer, register in AppKernel.php, add config to config/, update routing if needed. Four steps, all manual. ...

January 14, 2018 · 5 min · Guillaume Delré