<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>PHP &amp; Symfony Engineering Notes</title>
<link>https://php-freelance.com/blog/</link>
<atom:link href="https://php-freelance.com/blog/feed.xml" rel="self" type="application/rss+xml" />
<description>Technical write-ups on PHP, Symfony and domain modeling from a senior freelance developer since 2008. Real code, real trade-offs, no generic tutorials.</description>
<language>en</language>
<lastBuildDate>Thu, 24 Sep 2026 00:00:00 GMT</lastBuildDate>
<item>
<title>Recorded, Not Injected</title>
<link>https://php-freelance.com/blog/recorded-not-injected/</link>
<guid>https://php-freelance.com/blog/recorded-not-injected/</guid>
<pubDate>Thu, 24 Sep 2026 00:00:00 GMT</pubDate>
<description>Why a domain event has to wait until what it announces is true, with a full DDD booking aggregate: an AggregateRoot base class, recordThat(), and pullEvents().</description>
</item>
<item>
<title>The Readonly Trap</title>
<link>https://php-freelance.com/blog/the-readonly-trap/</link>
<guid>https://php-freelance.com/blog/the-readonly-trap/</guid>
<pubDate>Wed, 23 Sep 2026 00:00:00 GMT</pubDate>
<description>Why readonly alone doesn't make a PHP Value Object correct, with a full DDD booking aggregate: Entities, Value Objects, equals(), and where each one breaks.</description>
</item>
</channel>
</rss>
