<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/vendor/feed/atom.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
                        <id>https://freek.dev/feed/php</id>
                                <link href="https://freek.dev/feed/php" rel="self"></link>
                                <title><![CDATA[freek.dev - all PHP blogposts]]></title>
                    
                                <subtitle>All PHP blogposts on freek.dev</subtitle>
                                                    <updated>2026-07-29T17:23:14+02:00</updated>
                        <entry>
            <title><![CDATA[PHP version stats: July, 2026]]></title>
            <link rel="alternate" href="https://freek.dev/3171-php-version-stats-july-2026" />
            <id>https://freek.dev/3171</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Brendt shares fresh Packagist-based PHP version stats for July 2026: PHP 8.4 is now the most-used version, while PHP 8.5 reached 16% adoption after six months. He also notes that package minimum requirements still lag behind, with relatively few popular packages requiring a version that still gets active bugfix support.</p>


<a href='https://stitcher.io/blog/php-version-stats-july-2026'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-29T17:23:14+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Building an order fulfilment workflow in Laravel]]></title>
            <link rel="alternate" href="https://freek.dev/3170-building-an-order-fulfilment-workflow-in-laravel" />
            <id>https://freek.dev/3170</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Steve King builds a real order fulfilment flow to show how a workflow engine handles long-running processes in Laravel. The post covers steps, signals, retries, branching, human approval, compensation, and the surrounding tooling in one practical example.</p>


<a href='https://www.juststeveking.com/articles/building-an-order-fulfilment-workflow/'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-25T14:30:28+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Preventing SSRF in Laravel: Why Blocking Private IPs Fails]]></title>
            <link rel="alternate" href="https://freek.dev/3167-preventing-ssrf-in-laravel-why-blocking-private-ips-fails" />
            <id>https://freek.dev/3167</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>I found there wasn't any good SSRF prevention libraries for Laravel, so I built one. Very comprehensive tests based on this paper:
https://www.usenix.org/conference/usenixsecurity24/presentation/wessels</p>
<p>https://github.com/securized/laravel-ssrf</p>


<a href='https://securized.dev/laravel-ssrf-package'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-22T15:24:24+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[PHP Attributes: What, Why, How and When]]></title>
            <link rel="alternate" href="https://freek.dev/3166-php-attributes-what-why-how-and-when" />
            <id>https://freek.dev/3166</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>A deep dive into PHP attributes, from metadata and Reflection to practical design patterns, Laravel examples, performance, testing, and the cases where explicit code is better.</p>


<a href='https://wendelladriel.com/blog/php-attributes-what-why-how-and-when'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-21T14:43:26+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Supercharge your PHP apps with Go-powered PHP extensions]]></title>
            <link rel="alternate" href="https://freek.dev/3164-supercharge-your-php-apps-with-go-powered-php-extensions" />
            <id>https://freek.dev/3164</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>A practical conference session on building PHP extensions with Go and FrankenPHP, then wiring them into Laravel and Symfony as native-feeling features. It uses an in-memory LRU cache as the example and offers a nice tour of framework flexibility and PHP internals.</p>


<a href='https://phpconference.nl/session/supercharge-your-php-apps-with-go-powered-php-extensions/'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-17T14:30:31+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[New in PHP 8.6: Faster array_map with first-class callables]]></title>
            <link rel="alternate" href="https://freek.dev/3162-new-in-php-86-faster-array-map-with-first-class-callables" />
            <id>https://freek.dev/3162</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>In this video, Tideways shows how PHP 8.6 speeds up array_map when you use first-class callables.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/Bbc0fXNXB3U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
]]>
            </summary>
                                    <updated>2026-07-15T14:30:27+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[The Laravel Scheduler Under the Hood]]></title>
            <link rel="alternate" href="https://freek.dev/3161-the-laravel-scheduler-under-the-hood" />
            <id>https://freek.dev/3161</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>A deep dive into the Laravel Scheduler, from event registration and cron evaluation to mutexes, background processes, sub-minute tasks, and production-safe scheduling.</p>


<a href='https://wendelladriel.com/blog/the-laravel-scheduler-under-the-hood'>Read more</a>]]>
            </summary>
                                    <updated>2026-07-14T14:02:25+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Everything About the Context Facade]]></title>
            <link rel="alternate" href="https://freek.dev/3152-everything-about-the-context-facade" />
            <id>https://freek.dev/3152</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>A deep dive into Laravel Context, from request metadata and automatic log enrichment to hidden context, scoped values, queues, scheduled commands, and internals.</p>


<a href='https://wendelladriel.com/blog/everything-about-the-context-facade'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-29T14:13:28+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Improving Laravel Architecture With Expressive]]></title>
            <link rel="alternate" href="https://freek.dev/3134-improving-laravel-architecture-with-expressive" />
            <id>https://freek.dev/3134</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Learn how Expressive can improve a Laravel application by keeping Eloquent as the database layer while moving business logic to fully typed objects.</p>


<a href='https://wendelladriel.com/blog/improving-laravel-architecture-with-expressive'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-23T14:30:27+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Eloquent Query Classes Pattern]]></title>
            <link rel="alternate" href="https://freek.dev/3146-eloquent-query-classes-pattern" />
            <id>https://freek.dev/3146</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Learn how to use Eloquent Query Classes to organize important database logic in Laravel without adding a full repository layer.</p>


<a href='https://wendelladriel.com/blog/eloquent-query-classes-pattern'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-22T14:30:28+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Building RAG in Laravel: Four Ingestion Bugs That Silently Wreck Retrieval]]></title>
            <link rel="alternate" href="https://freek.dev/3144-building-rag-in-laravel-four-ingestion-bugs-that-silently-wreck-retrieval" />
            <id>https://freek.dev/3144</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Every Laravel RAG tutorial builds the same ingestion pipeline (chunk, embed, store) and stops the moment the agent answers on screen. None of them check whether retrieval is any good. But retrieval quality is decided at ingestion, before the model runs once, and four decisions there fail with no error, no exception, no failed test:</p>
<ul>
<li><strong>Chunking</strong> that severs the answer mid-sentence, so <code>answer@1</code> falls while <code>source hit@1</code> still looks healthy.</li>
<li>An <strong>HNSW index</strong> built with <code>vector_l2_ops</code> while you query with cosine <code>&lt;=&gt;</code>. Postgres silently ignores the index and scans every row. Laravel 13's native <code>whereVectorSimilarTo()</code> hardcodes <code>&lt;=&gt;</code>, so it's easier to hit than ever. Shown with <code>EXPLAIN</code>.</li>
<li>The <strong>embedding dimension</strong> baked into the <code>vector(1536)</code> column type, so &quot;shrink it to save storage&quot; is a migration plus a full re-embed that quietly drops retrieval to 47%.</li>
<li><strong>Ingesting and querying with different models</strong>, which turns every distance into noise.</li>
</ul>
<p>Each bug is real code from a working repo, proven against an eval suite. It's the prequel to my earlier &quot;Evaluating RAG in Laravel&quot; post: build it, prove it, tune it. Every example verified against <code>laravel/ai</code> v0.7.2 and pgvector, with the full repo to clone.</p>


<a href='https://mujahidabbas.dev/blog/building-rag-laravel-pgvector/'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-19T14:32:25+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[How PHP Attributes Changed the Way I Write Livewire]]></title>
            <link rel="alternate" href="https://freek.dev/3142-how-php-attributes-changed-the-way-i-write-livewire" />
            <id>https://freek.dev/3142</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Bert De Swaef shows how PHP attributes made his Livewire components easier to read by attaching validation, URL sync, and event listeners directly to the properties and methods they belong to. Nice piece on how attributes reduce mental overhead, improve IDE support, and make components feel more self-documenting.</p>


<a href='https://bert.gent/articles/2026-05-24/how-php-attributes-changed-the-way-i-write-livewire'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-17T12:30:28+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Rust Tutorial For PHP and JavaScript Developers]]></title>
            <link rel="alternate" href="https://freek.dev/3141-rust-tutorial-for-php-and-javascript-developers" />
            <id>https://freek.dev/3141</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[

<a href='https://youtu.be/lJdqrDFswns?si=xs8_bE4e1JwIsZHu'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-16T14:55:29+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[#[RouteParameter] Does Not Bind Your Model]]></title>
            <link rel="alternate" href="https://freek.dev/3137-routeparameter-does-not-bind-your-model" />
            <id>https://freek.dev/3137</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Michael Dyrynda explains a subtle Laravel gotcha: #[RouteParameter] only reads the current route parameter value, it does not perform implicit model binding. Good reminder that the controller signature still matters when you expect a bound model inside a form request.</p>


<a href='https://dyrynda.com.au/blog/route-parameters-can-hurt'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-12T14:30:26+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Prompt-Injection Guardrails in Laravel: Defend the Tools, Not the Prompt]]></title>
            <link rel="alternate" href="https://freek.dev/3136-prompt-injection-guardrails-in-laravel-defend-the-tools-not-the-prompt" />
            <id>https://freek.dev/3136</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>You can't out-prompt an attacker — to the model, your system instructions and a malicious support ticket are the same text. So stop defending the prompt and lock down the boundaries you actually control: tools scoped to the authenticated user server-side, middleware that screens and logs, output handled as untrusted input, a human in front of anything irreversible, and a fake-free test that fails CI the moment someone drops the auth scope.</p>


<a href='https://mujahidabbas.dev/blog/laravel-prompt-injection-guardrails/'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-11T14:10:30+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Logging is here!]]></title>
            <link rel="alternate" href="https://freek.dev/3147-logging-is-here" />
            <id>https://freek.dev/3147</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Flare now supports log collection for Laravel and PHP apps, with real-time filtering and search in the same polished interface. A nice overview of what logging adds and how to get started with the new SDK release.</p>


<a href='https://flareapp.io/blog/logging-is-here'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-09T14:30:28+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[The Reason I Love Tempest for APIs]]></title>
            <link rel="alternate" href="https://freek.dev/3127-the-reason-i-love-tempest-for-apis" />
            <id>https://freek.dev/3127</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Steve King explains why Tempest feels so nice for API work: typed request objects, declarative validation, route discovery, and a low-ceremony action flow. It is a good look at how the framework removes boilerplate without giving up clarity.</p>


<a href='https://www.juststeveking.com/articles/the-reason-i-love-tempest-for-apis/'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-03T14:30:27+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Using property hooks in PHP]]></title>
            <link rel="alternate" href="https://freek.dev/3125-using-property-hooks-in-php" />
            <id>https://freek.dev/3125</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Michael Dyrynda shows how PHP 8.4 property hooks can replace simple computed getter methods with virtual properties. He makes the case for using them when you want a clean, property-based API for derived values.</p>


<a href='https://dyrynda.com.au/blog/using-property-hooks-in-php'>Read more</a>]]>
            </summary>
                                    <updated>2026-06-01T14:30:31+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[Validating distinct data in requests]]></title>
            <link rel="alternate" href="https://freek.dev/3124-validating-distinct-data-in-requests" />
            <id>https://freek.dev/3124</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>Michael Dyrynda shows how Laravel's <code>distinct</code> validation rule can protect nested request payloads from duplicate reference values before they corrupt relationship mapping. He also highlights the <code>strict</code> and <code>ignore_case</code> options for cases where loose comparison is not enough.</p>


<a href='https://dyrynda.com.au/blog/validating-distinct-request-data'>Read more</a>]]>
            </summary>
                                    <updated>2026-05-31T14:30:37+02:00</updated>
        </entry>
            <entry>
            <title><![CDATA[The stack behind There There]]></title>
            <link rel="alternate" href="https://freek.dev/3133-the-stack-behind-there-there" />
            <id>https://freek.dev/3133</id>
            <author>
                <name><![CDATA[Freek Van der Herten]]></name>
                <email><![CDATA[freek@spatie.be]]></email>

            </author>
            <summary type="html">
                <![CDATA[<p>An inside look at the stack powering There There: Laravel, Inertia, React, TypeScript, Horizon, Reverb, and a bunch of Spatie packages and services. A nice overview of the pragmatic tooling choices behind the product.</p>


<a href='https://there-there.app/blog/the-stack-behind-there-there'>Read more</a>]]>
            </summary>
                                    <updated>2026-05-30T10:13:56+02:00</updated>
        </entry>
    </feed>
