<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mahdyar</title>
    <description>The latest articles on DEV Community by Mahdyar (@mahdyaralipor).</description>
    <link>https://dev.to/mahdyaralipor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2236873%2F57da6209-bcc2-42b3-8371-834777bb132f.jpg</url>
      <title>DEV Community: Mahdyar</title>
      <link>https://dev.to/mahdyaralipor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mahdyaralipor"/>
    <language>en</language>
    <item>
      <title>Awesome Laravel AI: Every Package, Tool and Guide for Building AI Agents with Laravel in One List</title>
      <dc:creator>Mahdyar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 12:36:28 +0000</pubDate>
      <link>https://dev.to/mahdyaralipor/awesome-laravel-ai-every-package-tool-and-guide-for-building-ai-agents-with-laravel-in-one-list-2pem</link>
      <guid>https://dev.to/mahdyaralipor/awesome-laravel-ai-every-package-tool-and-guide-for-building-ai-agents-with-laravel-in-one-list-2pem</guid>
      <description>&lt;p&gt;Laravel shipped a first-party AI SDK, an MCP toolkit, official agent skills and a skills directory — and community packages (RAG kits, evals, agent loops) are popping up everywhere. But they're scattered across GitHub, blog posts and Discord messages.&lt;/p&gt;

&lt;p&gt;So I put together &lt;strong&gt;awesome-laravel-ai&lt;/strong&gt;: one curated list with everything worth knowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Official pieces&lt;/strong&gt; — the AI SDK itself, its docs, the agent skills collection, the community skills directory, Boost, and the MCP toolkit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Community packages&lt;/strong&gt; — including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/MaestroError/LarAgent" rel="noopener noreferrer"&gt;LarAgent&lt;/a&gt; — full AI agent framework for Laravel&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/laragentic/agents" rel="noopener noreferrer"&gt;laragentic/agents&lt;/a&gt; — agentic loops (ReAct, plan-execute) on top of the official SDK&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/LarAIgent/larai-kit" rel="noopener noreferrer"&gt;LarAIgent/larai-kit&lt;/a&gt; — drop-in RAG: ingestion, pgvector/Pinecone search, streaming chat&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/vizra-ai/vizra-evals" rel="noopener noreferrer"&gt;vizra-ai/vizra-evals&lt;/a&gt; — write agent evals as Pest tests&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nightwatch.laravel.com" rel="noopener noreferrer"&gt;Nightwatch&lt;/a&gt; — monitoring with an MCP server, so agents can browse errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Learning&lt;/strong&gt; — the Laravel News skills-directory overview and the official Laravel AI blog (benchmarks, multi-agent workflows, MCP apps).&lt;/p&gt;

&lt;p&gt;Every link on the list is checked and working. The list is short on purpose — quality over quantity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Help grow it
&lt;/h2&gt;

&lt;p&gt;Know a Laravel+AI package, tool or guide that's missing? Open a PR — small focused ones get merged fast. Contribution guidelines are in the repo.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/mahdyaralipor/awesome-laravel-ai" rel="noopener noreferrer"&gt;https://github.com/mahdyaralipor/awesome-laravel-ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if it saves you a search someday, a ⭐ keeps it alive.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>laravel</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Jalali Dates in Modern PHP: Building ParsiDate — Immutable, Zero-Dependency, with Holidays Built In</title>
      <dc:creator>Mahdyar</dc:creator>
      <pubDate>Tue, 06 Oct 2026 11:55:03 +0000</pubDate>
      <link>https://dev.to/mahdyaralipor/jalali-dates-in-modern-php-building-parsidate-immutable-zero-dependency-with-holidays-built-in-5fi6</link>
      <guid>https://dev.to/mahdyaralipor/jalali-dates-in-modern-php-building-parsidate-immutable-zero-dependency-with-holidays-built-in-5fi6</guid>
      <description>&lt;p&gt;If you build software for 85+ million Persian speakers, you need Jalali (Solar Hijri) dates. And if you do it in PHP, you've probably met the usual suspects: libraries built a decade ago, &lt;code&gt;strftime()&lt;/code&gt; calls that PHP 8.1 deprecated, mutable date objects that cause spooky action-at-a-distance in queue workers, and holiday lists you have to maintain by hand.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;ParsiDate&lt;/strong&gt; to fix that for my own projects. It's now at v1.1.0, MIT licensed, with 136 passing tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require mahdyaralipor/parsidate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Design decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Immutable by default.&lt;/strong&gt; Every arithmetic method returns a new instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ParsiDate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$later&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// $date is untouched&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've ever debugged a Carbon object mutated three call frames away, you know why this matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Zero dependencies.&lt;/strong&gt; &lt;code&gt;composer.json&lt;/code&gt; requires exactly one thing: &lt;code&gt;php: ^8.1&lt;/code&gt;. No Carbon, no framework, no polyfills. It works in Laravel, Symfony, WordPress, or a bare script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Holidays are data, not your problem.&lt;/strong&gt; Official Iranian public holidays (1400–1406, verified date-by-date against the official calendar) ship inside the package, with an API for variable holidays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isHoliday&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;        &lt;span class="c1"&gt;// true on Nowruz&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;holidayName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;      &lt;span class="c1"&gt;// "جشن نوروز"&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addWorkdays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// skips Fridays + public holidays&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;workdaysUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Periods are iterable.&lt;/strong&gt; Date ranges are first-class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$period&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ParsiPeriod&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;ofMonth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1403&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$period&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;countWorkdays&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$period&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;overlap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// ParsiPeriod|null&lt;/span&gt;
&lt;span class="nv"&gt;$period&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;splitByDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// weekly chunks&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$period&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fridays&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$friday&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$friday&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y/m/d'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Persian digits everywhere.&lt;/strong&gt; Parsing and formatting both understand &lt;code&gt;۰۱۲۳۴۵۶۷۸۹&lt;/code&gt;, because real user input uses them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;ParsiDate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'۱۴۰۳/۰۶/۱۵'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;formatPersian&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y/m/d'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// ۱۴۰۳/۰۶/۱۵&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Hijri conversion included.&lt;/strong&gt; &lt;code&gt;$date-&amp;gt;toHijri()&lt;/code&gt; returns a value object with Arabic + Latin month names and array/JSON output. One honest caveat, documented in the README: it uses the tabular (arithmetic) calendar, so it can differ ±1–2 days from moon-sighting calendars.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Recurring events / RRULE-style helpers&lt;/li&gt;
&lt;li&gt;More calendar systems on request&lt;/li&gt;
&lt;li&gt;Framework bridges (a Laravel service provider is the most requested)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/mahdyaralipor/parsidate" rel="noopener noreferrer"&gt;https://github.com/mahdyaralipor/parsidate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you work with Jalali dates in production, I'd love to hear what your current setup is and where it hurts — that's what shapes the roadmap. And if it's useful, a ⭐ helps others find it.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>opensource</category>
      <category>php</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>My Laravel PR Was Auto-Closed in 16 Seconds — 3 Lessons From Contributing to laravel/framework</title>
      <dc:creator>Mahdyar</dc:creator>
      <pubDate>Sun, 04 Oct 2026 13:32:35 +0000</pubDate>
      <link>https://dev.to/mahdyaralipor/my-laravel-pr-was-auto-closed-in-16-seconds-3-lessons-from-contributing-to-laravelframework-3oj1</link>
      <guid>https://dev.to/mahdyaralipor/my-laravel-pr-was-auto-closed-in-16-seconds-3-lessons-from-contributing-to-laravelframework-3oj1</guid>
      <description>&lt;h1&gt;
  
  
  My Laravel PR Was Auto-Closed in 16 Seconds — 3 Lessons From Contributing to laravel/framework
&lt;/h1&gt;

&lt;p&gt;I recently backported a routing fix from Laravel 13.x to 12.x. The code change was 64 lines, all tests passed locally — and a bot still closed my PR 16 seconds after I opened it.&lt;/p&gt;

&lt;p&gt;Here's what happened and the three things I'll do differently next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The task: a clean 1:1 backport
&lt;/h2&gt;

&lt;p&gt;Issue &lt;a href="https://github.com/laravel/framework/issues/61788" rel="noopener noreferrer"&gt;#61788&lt;/a&gt; reported that on 12.x, &lt;code&gt;?&lt;/code&gt; in route parameters gets encoded (&lt;code&gt;?&lt;/code&gt; → &lt;code&gt;%3F&lt;/code&gt;), breaking URLs built with pre-encoded values. The fix had already landed on 13.x as PR &lt;a href="https://github.com/laravel/framework/pull/61610" rel="noopener noreferrer"&gt;#61610&lt;/a&gt;, which introduced a tiny &lt;code&gt;EncodedParameter&lt;/code&gt; wrapper so already-encoded values pass through &lt;code&gt;RouteUrlGenerator::encodeParameter()&lt;/code&gt; untouched.&lt;/p&gt;

&lt;p&gt;The 12.x branch had the exact pre-fix code, so the port was mechanical: one new file, a short-circuit in &lt;code&gt;encodeParameter()&lt;/code&gt;, and the regression test copied over. &lt;code&gt;RoutingUrlGeneratorTest&lt;/code&gt;: 59 tests, 286 assertions, all green. Pint clean. I opened the PR feeling good.&lt;/p&gt;

&lt;p&gt;Sixteen seconds later, it was closed. Not by a human — by &lt;code&gt;github-actions[bot]&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: Tick "Allow edits from maintainers" or don't bother
&lt;/h2&gt;

&lt;p&gt;The bot's message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We require that all PRs grant maintainer edit access before we review them… Please resubmit this PR from a personal GitHub account with maintainer permissions enabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Laravel won't even &lt;em&gt;look&lt;/em&gt; at a PR without the "Allow edits from maintainers" checkbox. When you open PRs from the GitHub web UI on your own fork, the box is usually ticked by default — but I created mine via the API, where it defaults to off.&lt;/p&gt;

&lt;p&gt;If you automate PR creation (scripts, API, bots), set &lt;code&gt;maintainer_can_modify: true&lt;/code&gt; explicitly. I resubmitted as &lt;a href="https://github.com/laravel/framework/pull/61871" rel="noopener noreferrer"&gt;#61871&lt;/a&gt; with the flag on, and the bot left it alone. One checkbox, sixteen seconds, an entire round-trip wasted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: Check for existing PRs before writing a single line
&lt;/h2&gt;

&lt;p&gt;Before picking the backport, I had shortlisted three issues — and two were already being handled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/laravel/framework/issues/61848" rel="noopener noreferrer"&gt;#61848&lt;/a&gt; (&lt;code&gt;logoutOtherDevices&lt;/code&gt; invalidating the current session) already had open PR &lt;a href="https://github.com/laravel/framework/pull/61851" rel="noopener noreferrer"&gt;#61851&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/laravel/framework/issues/61216" rel="noopener noreferrer"&gt;#61216&lt;/a&gt; (truncated &lt;code&gt;RequestException&lt;/code&gt; messages) had prior PRs attached.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub shows linked PRs right on the issue page (&lt;code&gt;closed_by_pull_requests&lt;/code&gt; / linked pull requests section). Thirty seconds of checking saved me from duplicating someone's work. Boring advice, but the backport only existed as an opportunity &lt;em&gt;because&lt;/em&gt; I checked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: Red CI isn't always your fault — prove it
&lt;/h2&gt;

&lt;p&gt;My resubmitted PR came back with a failing PHPStan job: 6 errors in &lt;code&gt;Support/Collection.php&lt;/code&gt; and &lt;code&gt;Support/LazyCollection.php&lt;/code&gt; about literal generics (&lt;code&gt;&amp;lt;'foo'&amp;gt;&lt;/code&gt; vs &lt;code&gt;string&lt;/code&gt;). Files I never touched.&lt;/p&gt;

&lt;p&gt;Instead of "fixing" unrelated code (never do that in someone else's repo), I ran the exact CI command locally against the &lt;strong&gt;clean base commit&lt;/strong&gt; — no changes of mine at all. It failed too, with pre-existing errors. That proves version drift between the pinned config and the current PHPStan release, not a regression from my change. I posted that evidence as a comment on the PR so maintainers can see at a glance that the red X isn't mine.&lt;/p&gt;

&lt;p&gt;The rule: if CI fails in files outside your diff, reproduce it on the base commit before touching anything. A comment with proof ("fails on &lt;code&gt;71cf667&lt;/code&gt; with zero changes applied") is worth more than a speculative fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Contributing to a project like &lt;code&gt;laravel/framework&lt;/code&gt; is 20% code and 80% process hygiene:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check for competing PRs first.&lt;/li&gt;
&lt;li&gt;Grant maintainer edit access (especially via API).&lt;/li&gt;
&lt;li&gt;When CI blames you for someone else's drift, prove it on a clean tree instead of "fixing" it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The backport itself? Three files, done in minutes. Everything around it took the afternoon. That's normal — and now it's written down so your afternoon goes faster than mine.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>5 PHP Features You're Probably Not Using (But Should)</title>
      <dc:creator>Mahdyar</dc:creator>
      <pubDate>Sun, 28 Jun 2026 10:59:27 +0000</pubDate>
      <link>https://dev.to/mahdyaralipor/5-php-features-youre-probably-not-using-but-should-133e</link>
      <guid>https://dev.to/mahdyaralipor/5-php-features-youre-probably-not-using-but-should-133e</guid>
      <description>&lt;h1&gt;
  
  
  5 PHP Features You're Probably Not Using (But Should)
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;These aren't obscure tricks. They're tools that ship with modern PHP — and once you start using them, you'll wonder how you lived without them.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Generators — Process 1 Million Rows with Almost Zero Memory
&lt;/h2&gt;

&lt;p&gt;Here's a scenario every backend developer has faced: you need to read a large CSV file, process it row by row, and do something with the data. The instinct is to load everything into an array first.&lt;/p&gt;

&lt;p&gt;That instinct will kill your server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The traditional approach:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgetcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$rows&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// everything lands in RAM&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 1 million rows = ~460MB RAM 💀&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'big.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With a Generator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Generator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgetcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// one row at a time, nothing more&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;fclose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$handle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 1 million rows = ~0.3MB RAM ✨&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;readCsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'big.csv'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only difference is &lt;code&gt;yield&lt;/code&gt; instead of &lt;code&gt;$rows[] =&lt;/code&gt;. But the impact is dramatic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real benchmark — 1 million rows, 42MB file:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Traditional&lt;/th&gt;
&lt;th&gt;Generator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Time&lt;/td&gt;
&lt;td&gt;6.5s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.67s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;462 MB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~0.3 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Result&lt;/td&gt;
&lt;td&gt;identical&lt;/td&gt;
&lt;td&gt;identical&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Generator is &lt;strong&gt;2.4× faster&lt;/strong&gt; and uses virtually no memory. PHP doesn't have to build a massive array in memory before you can start processing — it gives you one row, you process it, it gives you the next.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yield&lt;/code&gt; pauses the function, hands a value to the caller, then resumes exactly where it left off when the caller asks for the next value. The file handle stays open between calls — no jumping back to the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beyond CSV:&lt;/strong&gt; Generators shine anywhere you deal with large sequences — reading database results in chunks, paginating API responses, generating infinite sequences, or streaming log files in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Named Arguments — Never Misorder Parameters Again
&lt;/h2&gt;

&lt;p&gt;Quick quiz. What does this code do?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably need to open the docs. Is &lt;code&gt;true&lt;/code&gt; the &lt;code&gt;preserve_keys&lt;/code&gt; flag? Is &lt;code&gt;3&lt;/code&gt; the length? What's what?&lt;/p&gt;

&lt;p&gt;This is a bug waiting to happen. And it has happened to all of us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Named Arguments fix this entirely:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Before — which true is which?&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ After — reads like documentation&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;preserve_keys&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the real power isn't just readability. It's &lt;strong&gt;skipping optional parameters in the middle.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PHP has many built-in functions with optional parameters buried in the middle of their signatures. With positional arguments, you have to spell out every parameter until you reach the one you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Before — had to repeat ENT_QUOTES and 'UTF-8' just to reach double_encode&lt;/span&gt;
&lt;span class="nv"&gt;$safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;htmlspecialchars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ENT_QUOTES&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'UTF-8'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ After — jump straight to what you care about&lt;/span&gt;
&lt;span class="nv"&gt;$safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;htmlspecialchars&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;double_encode&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Named Arguments + Spread = clean dependency injection:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'table'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'limit'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'cache'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'orderBy'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// spread a named array directly into a constructor&lt;/span&gt;
&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And before you ask — no, there's no performance cost. In our benchmark of 1 million calls, named arguments were actually marginally &lt;em&gt;faster&lt;/em&gt; than positional ones (PHP 8's internal optimizer handles them efficiently).&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Fibers — The Foundation Under ReactPHP and Swoole
&lt;/h2&gt;

&lt;p&gt;Fibers are the most misunderstood feature on this list. They're not magic async/await. They won't automatically make your code run in parallel. But they are the primitive that makes modern PHP async frameworks possible.&lt;/p&gt;

&lt;p&gt;A Fiber is a function that can &lt;strong&gt;pause itself and hand control back to the caller&lt;/strong&gt; — then be resumed later from exactly where it left off.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$fiber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Fiber] starting"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'first pause'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// pause + send value out&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Fiber] resumed, got: &lt;/span&gt;&lt;span class="nv"&gt;$received&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fiber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;suspend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'second pause'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Fiber] resumed again, got: &lt;/span&gt;&lt;span class="nv"&gt;$received&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'done'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Main] starting fiber"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$yielded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                 &lt;span class="c1"&gt;// runs until first suspend&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Main] fiber paused, sent: &lt;/span&gt;&lt;span class="nv"&gt;$yielded&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$yielded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message one'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// resume, get next suspend value&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Main] fiber paused again, sent: &lt;/span&gt;&lt;span class="nv"&gt;$yielded&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;resume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message two'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// resume to completion&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Main] fiber returned: "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$fiber&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getReturn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Main] starting fiber
[Fiber] starting
[Main] fiber paused, sent: first pause
[Fiber] resumed, got: message one
[Main] fiber paused again, sent: second pause
[Fiber] resumed again, got: message two
[Main] fiber returned: done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the two-way communication. This is what separates Fibers from Generators — data flows both in and out. &lt;code&gt;suspend()&lt;/code&gt; sends a value to the caller; &lt;code&gt;resume($value)&lt;/code&gt; sends a value back into the Fiber.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key insight:&lt;/strong&gt; Fibers don't give you parallelism on their own. They give you &lt;em&gt;cooperative multitasking&lt;/em&gt; — each Fiber voluntarily yields control at a known point (an I/O wait, a network call, a database query). A scheduler can then run another Fiber while the first one waits.&lt;/p&gt;

&lt;p&gt;That scheduler is what ReactPHP, Swoole, and the Revolt event loop provide. PHP 8.1 gave us the primitive; the frameworks built async on top of it.&lt;/p&gt;

&lt;p&gt;If you're writing application code, you probably won't create Fibers directly. But understanding them tells you &lt;em&gt;why&lt;/em&gt; &lt;code&gt;amphp&lt;/code&gt; and &lt;code&gt;ReactPHP&lt;/code&gt; work the way they do — and why PHP async is fundamentally different from JavaScript's single-threaded event loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. First-Class Callable Syntax — Functions as Values, Finally Clean
&lt;/h2&gt;

&lt;p&gt;PHP has always let you pass functions as values. But the syntax was painful enough that most people just wrote inline closures instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before PHP 8.1 — verbose wrappers everywhere&lt;/span&gt;
&lt;span class="nv"&gt;$fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Closure&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fromCallable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'strlen'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Closure&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fromCallable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'strtoupper'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// or inline closures that wrap a single function call&lt;/span&gt;
&lt;span class="nv"&gt;$lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP 8.1 introduced a clean syntax: &lt;code&gt;functionName(...)&lt;/code&gt; creates a first-class Closure from any callable — built-in functions, static methods, instance methods, all of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ PHP 8.1+&lt;/span&gt;
&lt;span class="nv"&gt;$fn&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$upper&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strtoupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$obj&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$static&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Formatter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$lengths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where it really shines — &lt;strong&gt;pipeline patterns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$fns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;mixed&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;array_reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$carry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$carry&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"  Hello, World! This is PHP.  "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;strtolower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ['hello', 'world', 'this', 'is', 'php']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or &lt;strong&gt;validation chains&lt;/strong&gt; where each rule is just a callable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;mixed&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;callable&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$rules&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$rule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$rules&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;    &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'Minimum 8 characters'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/\d/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'Must contain a number'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;preg_match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/[A-Z]/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'Must contain uppercase'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, composable, testable — each rule is independently unit-testable, and adding a new one is a one-liner.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The Underrated Built-ins You Keep Reimplementing
&lt;/h2&gt;

&lt;p&gt;PHP's standard library has some genuinely useful functions that don't get enough attention. These aren't new features — they've been around for a while — but they solve problems that developers keep solving manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;array_is_list()&lt;/code&gt;&lt;/strong&gt; — PHP 8.1+&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before: manual check&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;array_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// now&lt;/span&gt;
&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;         &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nf"&gt;array_is_list&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essential when you're deciding whether to JSON-encode as &lt;code&gt;[]&lt;/code&gt; or &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;str_contains()&lt;/code&gt;, &lt;code&gt;str_starts_with()&lt;/code&gt;, &lt;code&gt;str_ends_with()&lt;/code&gt;&lt;/strong&gt; — PHP 8.0+&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;strpos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$needle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// now&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str_contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$needle&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str_starts_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str_ends_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.php'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mf"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more &lt;code&gt;!== false&lt;/code&gt; comparisons. No more accidentally treating &lt;code&gt;0&lt;/code&gt; as falsy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;array_any()&lt;/code&gt; and &lt;code&gt;array_all()&lt;/code&gt;&lt;/strong&gt; — PHP 8.5+&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before: manual loops or array_filter tricks&lt;/span&gt;
&lt;span class="nv"&gt;$hasAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// PHP 8.5&lt;/span&gt;
&lt;span class="nv"&gt;$hasAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;array_any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$allActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;array_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Putting It Together
&lt;/h2&gt;

&lt;p&gt;None of these features require a new framework or a major refactor. They're available in PHP 8.0–8.1+, which most production environments already run.&lt;/p&gt;

&lt;p&gt;The pattern across all five is the same: &lt;strong&gt;less boilerplate, clearer intent, better resource usage.&lt;/strong&gt; Generators keep memory under control. Named Arguments make signatures self-documenting. Fibers power the async ecosystem. First-class callables make functional composition clean. And the built-ins remove manual reimplementations.&lt;/p&gt;

&lt;p&gt;Start with whichever one solves a problem you're already facing. Once it clicks, the rest follow naturally.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;All benchmarks were run on PHP 8.3 CLI on Ubuntu. Source code for every example is available on &lt;a href="https://github.com/Mahdyaralipor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/em&gt;`&lt;/p&gt;

</description>
      <category>php</category>
      <category>programming</category>
      <category>backend</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
