RSSAmplifier

Blog

Loïc Faugeron

/RSS feed ↗147 posts

Latest posts

Turn your PHP app into a standalone binary

Edit (2026-03-26): added Distribution / Upgrade section. TL;DR : Prepare app for prod environment: no dev deps, autoloading optimisation (classmap authoritative), making .env.local.php from .env , no debug symfony cache, etc Compile the PHAR with Box Concatenate micro.sfx + dtk.phar into a self-contained binary with static-php-cli I've been building DTK , a PHP CLI tool that automates the…

PHP-TUI

BisouLand is an eXtreme Legacy (2005 LAMP) app, an idle browser game where players take each other's Love Points by blowing kisses across clouds. In the previous article , we built Qalin : BisouLand's Test Control Interface, a dedicated Symfony app that lets anyone on the team reach any game state on demand, without touching production code. Qalin already has three interfaces: CLI, API, and a Web…

eXtreme Legacy 11: A PHP Monorepo of Apps and Packages

BisouLand is an eXtreme Legacy (2005 LAMP) app, an idle browser game where players take each other's Love Points by blowing kisses across clouds. In this series, we're dealing with it as it is: a big ball of mud, a spaghetti code base written by a student learning web development from online tutorials. So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests 🎯 written End to…

Qalin: Test Control Interface, built with modern Symfony

BisouLand is an eXtreme Legacy (2005 LAMP) app, an idle browser game where players take each other's Love Points by blowing kisses across clouds. The app was built by a student while learning xHTML, CSS, PHP and MySQL from online tutorials. Maintaining this big ball of mud / spaghetti code can be a real challenge! In today's article, we'll explore how to improve Developer eXperience in such a…

eXtreme Legacy 9: XSS Vulnerability

🤘 Awakened by the sins of forgotten sanitization, the Cookie Burglar breaches the walls of client-side trust, stealing credentials from the altar of the Script Injector with its serpentine payloads! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests 🎯 written…

eXtreme Legacy 8: From MySQL to PostgreSQL

🤘 The Legacy Executioner casts MySQL into the void of deprecated technologies, summoning PostgreSQL from the northern lands to claim dominion over schemas with its superior type system and extension arsenal! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests…

eXtreme Legacy 7: Rector

🤘 Behold Rector, the Metamorphosis Overlord, wielding the dark grimoire of AST manipulation to transmute ancient incantations of PHP 5.6 into the blazing runes of PHP 8.x through unholy automated rituals! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests 🎯…

eXtreme Legacy 6: From PHP 5 to PHP 8

🤘 The Migration Warlord breaks the rusted shackles of PHP 5.6, leading the great exodus through the valleys of breaking changes, into the promised land of PHP 8.5 where type hints and constructor property promotion await in glory! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container…

eXtreme Legacy 5: PDO

🤘 The Parameter Paladin storms forth from the OWASP bastion, raising the impenetrable shield of Prepared Statements, against the shadow army of malicious injections, that seek to corrupt the sacred data temples! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke…

eXtreme Legacy 4: Coding Standards

🤘 The Coding Standards Inquisitor rises from the sulphurous pits of Legacy Chaos, brandishing the iron scriptures of Style Guides, purging the realm of inconsistent formatting with flames of automated linting! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests…

eXtreme Legacy 3: End to End Tests

🤘 The Beta Destroyer breaks free from the crypts of Manual Testing, forging unbreakable chains of End to End test scenarios, binding every component in the unholy covenant of automations! 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container 💨 written Smoke Tests This means we can run…

eXtreme Legacy 2: Smoke Tests

🤘 The Quality Avenger emerges from the burning forges of Coding Standards, smelting the ores of Static Analysis into the moulds of Automated Testing. 🔥 In this series, we're dealing with BisouLand, an eXtreme Legacy application (2005 LAMP spaghetti code base). So far, we have: 🐋 got it to run in a local container This means we can access it (http://localhost:8080/) and manually check it.…

eXtreme Legacy 1: Dockerizing a 2005 LAMP app

🤘 From the abyssal depths of forgotten servers, Docker the Void-Walker awakens to drag ancient LAMP stack from their tombs, wrapping them in the obsidian chains of containerization! 🔥 Back in 2005, I learned how to write Linux/Apache/MySQL/PHP websites thanks to the Site du Zero (SdZ), which is now known as Open Classrooms . I also used to play a web-browser game, similar to OGame , called…

My IDE is Vim

The keyboards leak molten steel, as Vim motions carve runes through silicon, the code prostrates itself before the LSP's omniscient eye: autocomplete rain Valhalla's arrows diagnostics burn syntax errors and typos alike go-to-definition shatters dimensional barriers like the Bifrost's rainbow bridge phpactor descends as the shape-shifting overlord who bends variables and transmutes classes into…

My Dotfiles

Through the storm of scattered settings, your dotfiles emerge as the lightning-born shepherds that bind chaos to your will. Why? What are dotfiles? How to manage them? My system My Framework Conclusion Why? My dotfiles repository is how I backup, restore and synchronise my shell / system preferences and settings. I felt the need to do so back in 2014, when I had 3 computers (personal desktop,…

My Git Workflow

TL;DR : git checkout -b FEAT-4423-my-feature from main git rebase main to update git merge --no-ff feature back in main Wield the crimson blade of version control, where every commit carves your legacy into the eternal codex of time. I wrote about my git workflow back in 2014 , which really was just @jbenet 's 2013 simple git branching model . I very much like this workflow as I still use it, a…

My Symfony Makefile

Note : Updated on 2026-02-23. For a Docker-based Symfony project, without Make , typing commands like running tests can quickly become cumbersome: docker compose exec app php vendor/bin/phpunit --testdox Make allows you to define a list of "rules" that provide: simple commands (eg make phpunit ) environment abstraction (eg make console env=prod ) built-in documentation (run make to list available…

My Symfony Dockerfile

Dockerize your PHP / Symfony application, to eliminate "works on MY machine". I'm describing here a solution that ensures consistent development environment, to run the project locally with just a few commands, without having to worry about: PHP version / extensions database / search engine / messaging queue / services setup Dockerfile Dockerignore Compose Going further SQLite Dockerfile The…

PHPUnit Best Practices (Ultimate Guide)

Edit : brought up to date on 2026-02-27. Forge battle-tested code, under the hammer of PHPUnit. Unit Tests Factory Methods Attributes Data Providers Testdox Coding Standards Principles Mocking Integration Tests Smoke Tests Useful CLI options Configuration Resources Unit Tests Here's a unit test for a Username value object: <?php declare(strict_types=1); namespace App\Tests\Unit; use…

PHP devs are Pirates

TL;DR : Arrr, PHP be a cunning pirate, pilferin' ideas from other languages to stay ahead o' the fleet. 'Tis true, PHP is no bonny innovator, but it be masterful at plunderin' and adaptin' features, keepin' its sails full and its reputation mighty in the tech seas. Pádraic Brady. 2012. PHP: a Pillagin Pirate PHP has a long history of adopting, porting, and emulating successful ideas and tools from…

My role as a Lead PHP Engineer

About me In September 2014, I left SensioLabs (the creator of the Symfony Framework) to work as a PHP/Symfony Developer at Foodity, a London start-up that created a service allowing people to add ingredients from online recipes to the basket of the retailer of their choice. After 9 months, I pitched an idea to the CEO: we had a platform that theoretically allowed us to add ANY product to the…

Don&#039;t mock what you don&#039;t own -- phpspec isn&#039;t a test framework

TL;DR: phpspec isn't a test framework. It's a code designing/modeling tool. Something feels wrong Looking at some 2014 code of mine, I found the following test: <?php namespace spec\Memio\SpecGen\CodeEditor; use Gnugat\Redaktilo; use Memio\Model; use Memio\PrettyPrinter\PrettyPrinter; use Memio\SpecGen\CodeEditor\InsertConstructor; use Memio\SpecGen\CodeEditor\InsertConstructorHandler; use…

phpspec tip: don&#039;t mock SUT inputs

Looking at some old code of mine, I've found the following test: <?php namespace spec\Memio\SpecGen\GenerateMethod; use Memio\Model\File; use Memio\Model\Method; use Memio\Model\Objekt; use Memio\SpecGen\GenerateMethod\GeneratedMethod; use PhpSpec\Console\ConsoleIO; use PhpSpec\ObjectBehavior; class LogGeneratedMethodListenerSpec extends ObjectBehavior { function let(ConsoleIO $io) {…

Strategy Pattern, Symfony and autowiring

TL;DR : Since Symfony 5.3 Tag the "Strategy" Interface with the attribute [#AutoconfigureTag] : <?php use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; #[AutoconfigureTag] interface Strategy { // Add your Strategy methods below, for example // (please use a more descriptive name than "algorithm"...): public function algorithm(); // *IF* your Strategies need to be executed in a…

PHPUnit setUp() is a lie

PHPUnit creates as many instances a Test Class, as it has test methods. Proof (and it gets worse) Let's set up a project to verify our claim: mkdir /tmp/phpunit-is-a-cake && cd "$_" composer init --no-interaction --name 'follow/the-white-rabbit' --type project --autoload '.' composer require -o --dev phpunit/phpunit:^9.6 Next we write a catchy test: <?php declare(strict_types=1); use…

ChatGPT: fluff or not? SpecBDD

Now that a couple of months have passed since its over hyped launch, surely ChatGPT has found some use cases where it could be of any actual use. Or is it all fluff? Let's find out. In my quest to find a use for ChatGPT in my day to day developer activity, I've finally found a helpful scenario! Let me walk you through my findings about ChatGPT and its "Spec Gen" capacity, so we can learn a thing…

ChatGPT: fluff or not? Goldfish Memory

Now that a couple of months have passed since its over hyped launch, surely ChatGPT has found some use cases where it could be of any actual use. Or is it all fluff? Let's find out. In my quest to find a use for ChatGPT in my day to day developer activity, I've stumbled upon this article: a 175-Billion-Parameter Goldfish , from Allen Pike . Granted, this doesn't bring me anywhere close to my…

ChatGPT: fluff or not? Academic Prompt Engineering

Now that a couple of months have passed since its over hyped launch, surely ChatGPT has found some use cases where it could be of any actual use. Or is it all fluff? Let's find out. In my quest to find a use for ChatGPT in my day to day developer activity, I've stumbled upon this online course website: Learn Prompting , an initiative lead by Sander Schulhoff , with contributions from Towards AI .…

ChatGPT: fluff or not? Prompt Engineering

Now that a couple of months have passed since its over hyped launch, surely ChatGPT has found some use cases where it could be of any actual use. Or is it all fluff? Let's find out. In my quest to find a use for ChatGPT in my day to day developer activity, I've stumbled upon this video: ChatGPT Prompt Engineering: How to Write a Story , by Kris - All About AI ). Granted, story writing is a bit…

Short Identifier

Sometimes resources can be identified by one of their attributes (a name, title, slug) and sometimes they can't (no name, or confidential name). In the later case, an ID needs to be artificially crafted. Two of the popular strategies is to use either an auto incremental one or a universally unique one, however when it comes to share them publicly, both strategies present some drawbacks Auto…

PragmatiClean - Command Bus

TL;DR : Use Command Bus pattern in your controllers, but drop the bus. The Command Bus pattern relies on 3 types of classes: The first one is the Command : its class name should describe the intended action in an imperative manner (eg SubmitNewQuote , AssignReviewers , etc) it is constructed using the input parameters (eg a Request's query/post/header parameters, a Console's input argument/option,…

PragmatiClean - introduction

There are only 10 types of debates in the software world, Clean Code v Pragmatic Code and those which don't matter. In this new series we'll see how to stop wasting time arguing which one is best and start using both instead. What's Clean Code? Clean Code is about writing for the long term, usually by structuring it with the help of Design Patterns and Principles. The assumption is that everything…

Links from 2016

TL;DR : Links I tweeted during 2016 Last year my interests seemed to have been split in three periods: beginning of the year: CQRS / ES and Mono Repo middle of the year: Event Driven Architecture and async end of the year: Artificial Intelligence I've also discovered two inspiring talks, I highly recommend you to watch them: Surgical Refactors by Justin Searl . It was a follow up of his also…

Mars Rover, Locating moving

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and the second one about driving it. We're…

Mars Rover, Locating geolocation

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and the second one about driving it. We're…

Mars Rover, Locating refactoring

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and the second one about driving it. We're…

Mars Rover, Locating handler

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and the second one about driving it. We're…

Mars Rover, Locating package

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and the second one about driving it. We're…

Mars Rover, Driving event

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and we've started the second one about…

Mars Rover, Driving instruction

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We've already developed the first use case about landing the rover on mars, and we've started the second one about…

Mars Rover, Driving

In this series we're building the software of a Mars Rover, according to the following specifications . It allows us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) We just finished developing the first use case, so we can now get cracking on the second one, Driving the rover: Once a…

Mars Rover, Event Sourcing code

In this series we're building the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Up until now, we've implemented the first use case, "Landing a rover on Mars": Mars Rovers need first to be landed…

Mars Rover, Event Sourcing package

In this series we're building the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Up until now, we've implemented the first use case, "Landing a rover on Mars": Mars Rovers need first to be landed…

Mars Rover, Landing event

In this series we're going to build the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Previously we've created a navigation package , and in it a LandRover class that validates input parameters…

Mars Rover, Landing orientation

In this series we're going to build the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Previously we've created a navigation package , and in it a LandRover class that validates input parameters…

Mars Rover, Landing coordinates

In this series we're going to build the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Previously we've created a navigation package , and in it a LandRover class that validates input parameters…

Mars Rover, Landing

In this series we're going to build the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) Previously we've created a navigation package , we can now start developing the first use case: Mars Rovers…

Mars Rover, Initialization

In this series we're going to build the software of a Mars Rover, according to the following specifications . It will allow us to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) But first, we need to initialize our project. Creating the repository Let's start by creating a new git…

Mars Rover, Introduction

Welcome to this Mars Rover series where we're going to practice the followings: Monolithic Repositories (MonoRepo) Command / Query Responsibility Segregation (CQRS) Event Sourcing (ES) Test Driven Development (TDD) In this introductory article, we're simply going to describe our Mars Rover specifications. Note : This programming exercise originally comes from Dallas Hack Club , which is now…

Towards CQRS, Search Engine

TL;DR : A Search Engine component can help you get the CQRS "Query" part right. The Command / Query Responsibility Segregation (CQRS) principle states that "write" and "read" logic should be separated. For example a single "Publisher" server (write) with many "Subscribers" servers (read) is a macro example of applying this principle, and an API that defines a read endpoint free from write side…