<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Cogway</title>
    <link>https://cogway.dev/</link>
    <description>Interactive explainers for Laravel and PHP. One concept at a time, turned into something you can step through, break, and run again.</description>
    <language>en</language>
    <atom:link href="https://cogway.dev/rss.xml" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Sat, 26 Sep 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>Why one agent question costs four requests</title>
      <link>https://cogway.dev/explainers/agent-tool-loop/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/agent-tool-loop/</guid>
      <description>prompt() is a loop. Every pass resends your instructions, your tool schemas and the whole conversation, so three tool calls cost four provider requests.</description>
      <pubDate>Sat, 26 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>PHP 8.6 partial application: why the timestamp never moves</title>
      <link>https://cogway.dev/explainers/partial-application/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/partial-application/</guid>
      <description>The arguments you supply around a placeholder are evaluated once, when you create the partial, and frozen into it for every call after that.</description>
      <pubDate>Sat, 26 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why raising your confidence threshold does not make it safer</title>
      <link>https://cogway.dev/explainers/confidence-threshold/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/confidence-threshold/</guid>
      <description>A threshold only tests the number the model states about itself. Against a model that states 0.95 on everything, no setting of the dial excludes the mistakes.</description>
      <pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>What singleton means when the process does not die</title>
      <link>https://cogway.dev/explainers/container-binding/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/container-binding/</guid>
      <description>bind builds a new instance every time, singleton keeps one for as long as the container lives, and scoped keeps one per request. On a persistent worker that difference is a data leak between requests.</description>
      <pubDate>Sat, 19 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>What a row lock actually locks</title>
      <link>https://cogway.dev/explainers/row-locks-deadlock/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/row-locks-deadlock/</guid>
      <description>An update with no index on the filtered column locks every row it scanned, not the rows it changed. And a lock wait timeout kills one statement, while a deadlock kills the whole transaction.</description>
      <pubDate>Sat, 19 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why your JSON array turned into an object</title>
      <link>https://cogway.dev/explainers/array-keys/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/array-keys/</guid>
      <description>A PHP array is an ordered hashmap, and a list is only an appearance its keys give it. Remove one element and json_encode changes the shape of your API response, with nothing to warn you.</description>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why your observer did not run</title>
      <link>https://cogway.dev/explainers/model-events/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/model-events/</guid>
      <description>An observer runs when a model changes, not when a row changes. A query builder update writes every matching row and fires nothing, so whatever the observer kept in step is now behind.</description>
      <pubDate>Fri, 18 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why strlen and mb_strlen disagree about one string</title>
      <link>https://cogway.dev/explainers/bytes-vs-characters/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/bytes-vs-characters/</guid>
      <description>A PHP string is a row of bytes, not a row of characters. strlen counts bytes, mb_strlen counts code points, and grapheme_strlen counts what a reader can see. Cutting with the wrong one breaks the text in two different ways.</description>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why chunking can skip half your rows</title>
      <link>https://cogway.dev/explainers/chunk-skips-rows/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/chunk-skips-rows/</guid>
      <description>chunk() pages with LIMIT and OFFSET and re-runs the query each time. Write to the column you filtered on and rows shift out from under it, so the next offset starts past rows nobody ever visited.</description>
      <pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Catastrophic backtracking: when one regex melts a CPU</title>
      <link>https://cogway.dev/explainers/catastrophic-backtracking/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/catastrophic-backtracking/</guid>
      <description>A nested quantifier makes the number of paths double with every letter, and it is the failing input that is slow. PHP gives up and returns false.</description>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Magic methods: how $user-&gt;name works when there is no name</title>
      <link>https://cogway.dev/explainers/magic-methods/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/magic-methods/</guid>
      <description>Magic methods do not run first. A declared, accessible member always wins, and __get and __call are only the fallback when ordinary lookup finds nothing.</description>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>The middleware pipeline, and where the response comes back through</title>
      <link>https://cogway.dev/explainers/middleware-pipeline/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/middleware-pipeline/</guid>
      <description>Middleware is not a list of filters run once on the way in. Each one wraps the request and the response, so the after halves run in reverse.</description>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Sanctum: a token or a cookie, depending on who is calling</title>
      <link>https://cogway.dev/explainers/sanctum-token-vs-session/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/sanctum-token-vs-session/</guid>
      <description>Sanctum authenticates two callers behind one guard: your own SPA by session cookie, a mobile client by bearer token. A token in your own SPA is the mistake.</description>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>How Eloquent casts raw database values into objects</title>
      <link>https://cogway.dev/explainers/attribute-casting/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/attribute-casting/</guid>
      <description>Model columns are not typed properties. They live in an array of raw values, and $casts converts them on read. isDirty compares them cast, not only raw.</description>
      <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>The cache stampede, and what a lock prevents</title>
      <link>https://cogway.dev/explainers/cache-stampede/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/cache-stampede/</guid>
      <description>Cache::remember protects the database only while the value is warm. When a key expires, every concurrent request runs the callback. A lock collapses it to one.</description>
      <pubDate>Tue, 04 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>When PHP copies a value, and when it shares it</title>
      <link>https://cogway.dev/explainers/references-memory/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/references-memory/</guid>
      <description>PHP assigns arrays by value, but defers the copy until a write. A reference is the opposite: two names, one slot. Copy-on-write and the foreach trap follow.</description>
      <pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>What a nested transaction actually rolls back</title>
      <link>https://cogway.dev/explainers/transaction-rollback/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/transaction-rollback/</guid>
      <description>A nested DB::transaction is a savepoint, not its own transaction. An inner commit runs no SQL, and nothing is durable until the outermost commit.</description>
      <pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why a projection is a view, not the source of truth</title>
      <link>https://cogway.dev/explainers/event-sourcing/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/event-sourcing/</guid>
      <description>A projection is one of many views folded from the event stream. Add a projector after the fact, replay it, and it rebuilds from events that already existed.</description>
      <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why eager loading changes the number of queries</title>
      <link>https://cogway.dev/explainers/n-plus-one/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/n-plus-one/</guid>
      <description>with() is not an optimisation you sprinkle on. It changes when your queries happen. Drive the loop and watch the counter.</description>
      <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why a failed job does not go straight to failed_jobs</title>
      <link>https://cogway.dev/explainers/queue-retries/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/queue-retries/</guid>
      <description>A thrown job is released and retried after a backoff. $tries counts total attempts, not retries. Killing the worker does not fail the job.</description>
      <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Why == and === are not the same comparison</title>
      <link>https://cogway.dev/explainers/type-juggling/</link>
      <guid isPermaLink="true">https://cogway.dev/explainers/type-juggling/</guid>
      <description>PHP&apos;s == does not compare values by eye. It coerces both sides to a common type first, following fixed rules, and one of those rules changed in PHP 8.</description>
      <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>
