<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Utsav Somaiya</title>
        <link>https://utsavsomaiya.in</link>
        <description>Your blog description</description>
        <lastBuildDate>Mon, 07 Sep 2026 01:45:48 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Utsav Somaiya</title>
            <url>https://utsavsomaiya.in/favicon.ico</url>
            <link>https://utsavsomaiya.in</link>
        </image>
        <copyright>All rights reserved 2026</copyright>
        <item>
            <title><![CDATA[Dispatching Alpine Events Between Livewire Components]]></title>
            <link>https://utsavsomaiya.in/articles/dispatching-alpine-events-between-livewire-components</link>
            <guid>https://utsavsomaiya.in/articles/dispatching-alpine-events-between-livewire-components</guid>
            <pubDate>Sat, 07 Mar 2026 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>Sometimes the cleanest Livewire fix is not another layer of abstraction.</p>
<p>It is just this:
dispatch a small Alpine event from the place where the interaction happens,
let another Livewire component listen to it,
and make the UI feel instant before the server round-trip finishes.</p>
<p>That pattern has been stuck in my head ever since this moment from Caleb's talk:</p>
<figure class="not-prose my-10 "><div class="overflow-hidden rounded-[1.8rem] border border-zinc-200/80 bg-white/80 shadow-[0_24px_60px_-40px_rgba(15,23,42,0.35)] dark:border-white/10 dark:bg-zinc-950/70 dark:shadow-[0_30px_80px_-50px_rgba(0,0,0,0.82)]"><div class="aspect-video w-full"><iframe src="https://www.youtube.com/embed/dChxb6daTGA?rel=0&amp;modestbranding=1&amp;start=932" title="Caleb Porzio mentioning Utsav" class="h-full w-full" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe></div></div><figcaption class="mt-3 text-sm leading-6 text-zinc-500 dark:text-zinc-400">A quick Caleb Porzio moment that made me think again about small, sharp Livewire interaction patterns.</figcaption></figure>
<h2>The Shape Of The Problem</h2>
<p>One component owns the action.
Another component somewhere else on the page needs to react to it.</p>
<p>For example:</p>
<ul>
<li>a row action updates a negotiation state</li>
<li>a summary card needs to refresh</li>
<li>a badge count should move instantly</li>
</ul>
<p>I did not want to refresh everything.
I also did not want to build a big store just to move one piece of information across the page.</p>
<h2>The Source Component</h2>
<p>The first component handles the click, updates the visible state optimistically, and dispatches a browser event with the useful details.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-blade"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#24292E">&lt;</span><span style="color:#22863A">div</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#24292E">    </span><span style="color:#6F42C1">x-data</span><span style="color:#24292E">=</span><span style="color:#032F62">"{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#032F62">        approved: </span><span style="color:#6F42C1">@js</span><span style="color:#032F62">(</span><span style="color:#24292E">$approved</span><span style="color:#032F62">),</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#032F62">        pending: false,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#032F62">        async approve() {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#032F62">            if (this.pending) return</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#032F62">            this.pending = true</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#032F62">            this.approved = true</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#032F62">            $dispatch('negotiation-approved', {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#032F62">                negotiationId: </span><span style="color:#6F42C1">@js</span><span style="color:#032F62">(</span><span style="color:#24292E">$negotiation</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">id</span><span style="color:#032F62">),</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#032F62">                approved: true,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#032F62">            })</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#032F62">            try {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#032F62">                await $wire.approve()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#032F62">            } catch (error) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#032F62">                this.approved = false</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#032F62">                $dispatch('negotiation-approved', {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#032F62">                    negotiationId: </span><span style="color:#6F42C1">@js</span><span style="color:#032F62">(</span><span style="color:#24292E">$negotiation</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">id</span><span style="color:#032F62">),</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#032F62">                    approved: false,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#032F62">                })</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#032F62">            } finally {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#032F62">                this.pending = false</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#032F62">            }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">28</span><span style="color:#032F62">        }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">29</span><span style="color:#032F62">    }"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">30</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">31</span><span style="color:#24292E">    &lt;</span><span style="color:#22863A">button</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">32</span><span style="color:#24292E">        </span><span style="color:#6F42C1">type</span><span style="color:#24292E">=</span><span style="color:#032F62">"button"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">33</span><span style="color:#24292E">        </span><span style="color:#6F42C1">x-on:click</span><span style="color:#24292E">=</span><span style="color:#032F62">"approve()"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">34</span><span style="color:#24292E">        </span><span style="color:#6F42C1">x-bind:disabled</span><span style="color:#24292E">=</span><span style="color:#032F62">"pending"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">35</span><span style="color:#24292E">        </span><span style="color:#6F42C1">class</span><span style="color:#24292E">=</span><span style="color:#032F62">"rounded-full border px-4 py-2"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">36</span><span style="color:#24292E">    &gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">37</span><span style="color:#24292E">        &lt;</span><span style="color:#22863A">span</span><span style="color:#24292E"> </span><span style="color:#6F42C1">x-show</span><span style="color:#24292E">=</span><span style="color:#032F62">"!pending &amp;&amp; !approved"</span><span style="color:#24292E">&gt;Approve&lt;/</span><span style="color:#22863A">span</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">38</span><span style="color:#24292E">        &lt;</span><span style="color:#22863A">span</span><span style="color:#24292E"> </span><span style="color:#6F42C1">x-show</span><span style="color:#24292E">=</span><span style="color:#032F62">"pending"</span><span style="color:#24292E">&gt;Approving...&lt;/</span><span style="color:#22863A">span</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">39</span><span style="color:#24292E">        &lt;</span><span style="color:#22863A">span</span><span style="color:#24292E"> </span><span style="color:#6F42C1">x-show</span><span style="color:#24292E">=</span><span style="color:#032F62">"!pending &amp;&amp; approved"</span><span style="color:#24292E">&gt;Approved&lt;/</span><span style="color:#22863A">span</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">40</span><span style="color:#24292E">    &lt;/</span><span style="color:#22863A">button</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">41</span><span style="color:#24292E">&lt;/</span><span style="color:#22863A">div</span><span style="color:#24292E">&gt;</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-blade"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">div</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#7FDBCA">    </span><span style="color:#C5E478">x-data</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#ECC48D">        approved: </span><span style="color:#82AAFF">@js</span><span style="color:#ECC48D">(</span><span style="color:#BEC5D4">$approved</span><span style="color:#ECC48D">),</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#ECC48D">        pending: false,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#ECC48D">        async approve() {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#ECC48D">            if (this.pending) return</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#ECC48D">            this.pending = true</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#ECC48D">            this.approved = true</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#ECC48D">            $dispatch('negotiation-approved', {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#ECC48D">                negotiationId: </span><span style="color:#82AAFF">@js</span><span style="color:#ECC48D">(</span><span style="color:#BEC5D4">$negotiation</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#BEC5D4">id</span><span style="color:#ECC48D">),</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#ECC48D">                approved: true,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#ECC48D">            })</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#ECC48D">            try {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#ECC48D">                await $wire.approve()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#ECC48D">            } catch (error) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#ECC48D">                this.approved = false</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#ECC48D">                $dispatch('negotiation-approved', {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#ECC48D">                    negotiationId: </span><span style="color:#82AAFF">@js</span><span style="color:#ECC48D">(</span><span style="color:#BEC5D4">$negotiation</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#BEC5D4">id</span><span style="color:#ECC48D">),</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#ECC48D">                    approved: false,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#ECC48D">                })</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#ECC48D">            } finally {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#ECC48D">                this.pending = false</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#ECC48D">            }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">28</span><span style="color:#ECC48D">        }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">29</span><span style="color:#ECC48D">    }</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">30</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">31</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">button</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">32</span><span style="color:#7FDBCA">        </span><span style="color:#C5E478">type</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">button</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">33</span><span style="color:#7FDBCA">        </span><span style="color:#C5E478">x-on:click</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">approve()</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">34</span><span style="color:#7FDBCA">        </span><span style="color:#C5E478">x-bind:disabled</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">pending</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">35</span><span style="color:#7FDBCA">        </span><span style="color:#C5E478">class</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">rounded-full border px-4 py-2</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">36</span><span style="color:#7FDBCA">    &gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">37</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">x-show</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">!pending &amp;&amp; !approved</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB">Approve</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">38</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">x-show</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">pending</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB">Approving...</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">39</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">x-show</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">!pending &amp;&amp; approved</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB">Approved</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">span</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">40</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">button</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">41</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">div</span><span style="color:#7FDBCA">&gt;</span></div></code></pre></div>
<p>That part matters:
the user sees the state move immediately.
The server still confirms the truth, but the interface does not feel late.</p>
<h2>The Other Livewire Component</h2>
<p>Now another component can listen for that event with Alpine and hand control back to its own <code>$wire</code>.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-blade"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#24292E">&lt;</span><span style="color:#22863A">div</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#24292E">    </span><span style="color:#6F42C1">x-data</span><span style="color:#24292E">=</span><span style="color:#032F62">"{ approvedCount: </span><span style="color:#6F42C1">@js</span><span style="color:#032F62">(</span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">approvedCount</span><span style="color:#032F62">) }"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#24292E">    </span><span style="color:#6F42C1">x-on:negotiation-approved.window</span><span style="color:#24292E">=</span><span style="color:#032F62">"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#032F62">        approvedCount = $event.detail.approved</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#032F62">            ? approvedCount + 1</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#032F62">            : Math.max(approvedCount - 1, 0)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#032F62">        $wire.refreshApprovedCount()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#032F62">    "</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">    &lt;</span><span style="color:#22863A">p</span><span style="color:#24292E"> </span><span style="color:#6F42C1">class</span><span style="color:#24292E">=</span><span style="color:#032F62">"text-sm text-zinc-500"</span><span style="color:#24292E">&gt;Approved negotiations&lt;/</span><span style="color:#22863A">p</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">    &lt;</span><span style="color:#22863A">p</span><span style="color:#24292E"> </span><span style="color:#6F42C1">class</span><span style="color:#24292E">=</span><span style="color:#032F62">"text-3xl font-semibold"</span><span style="color:#24292E"> </span><span style="color:#6F42C1">x-text</span><span style="color:#24292E">=</span><span style="color:#032F62">"approvedCount"</span><span style="color:#24292E">&gt;&lt;/</span><span style="color:#22863A">p</span><span style="color:#24292E">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#24292E">&lt;/</span><span style="color:#22863A">div</span><span style="color:#24292E">&gt;</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-blade"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">div</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#7FDBCA">    </span><span style="color:#C5E478">x-data</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">{ approvedCount: </span><span style="color:#82AAFF">@js</span><span style="color:#ECC48D">(</span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">approvedCount</span><span style="color:#ECC48D">) }</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#7FDBCA">    </span><span style="color:#C5E478">x-on:negotiation-approved.window</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#ECC48D">        approvedCount = $event.detail.approved</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#ECC48D">            ? approvedCount + 1</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#ECC48D">            : Math.max(approvedCount - 1, 0)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#ECC48D">        $wire.refreshApprovedCount()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#ECC48D">    </span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">p</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">class</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">text-sm text-zinc-500</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB">Approved negotiations</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">p</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">&lt;</span><span style="color:#CAECE6">p</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">class</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">text-3xl font-semibold</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA"> </span><span style="color:#C5E478">x-text</span><span style="color:#7FDBCA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">approvedCount</span><span style="color:#D9F5DD">"</span><span style="color:#7FDBCA">&gt;&lt;/</span><span style="color:#CAECE6">p</span><span style="color:#7FDBCA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#7FDBCA">&lt;/</span><span style="color:#CAECE6">div</span><span style="color:#7FDBCA">&gt;</span></div></code></pre></div>
<p>I like this because the boundary stays clear:</p>
<ul>
<li>Alpine handles the tiny front-end interaction</li>
<li>the event carries only what the rest of the page needs</li>
<li>the second Livewire component decides how to reconcile itself</li>
</ul>
<h2>Why The Optimistic Part Helps</h2>
<p>Without the optimistic step, the interaction waits on the network.
That usually means:</p>
<ul>
<li>the button feels heavier than it should</li>
<li>the badge updates too late</li>
<li>the UI looks unsure even when the action is simple</li>
</ul>
<p>With the optimistic step, the page feels more direct.
If the backend disagrees, you still have a rollback path.
But most of the time, the interface gets to feel correct at the exact moment the user clicked.</p>
<h2>Why I Reach For This</h2>
<p>This pattern is small, but it scales well.</p>
<p>It works when:</p>
<ul>
<li>you want components to stay separate</li>
<li>you only need to share one small state change</li>
<li>you want a faster feeling without making the architecture messy</li>
</ul>
<p>For me, this is the sweet spot:
Alpine for the interaction edge,
Livewire for the server-backed truth,
and just enough optimism to make the whole thing feel alive.</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Does a Senior Need a Senior? The Laravel and Livewire Edition]]></title>
            <link>https://utsavsomaiya.in/articles/does-a-senior-need-senior</link>
            <guid>https://utsavsomaiya.in/articles/does-a-senior-need-senior</guid>
            <pubDate>Thu, 31 Oct 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>You’d think a senior developer, especially in Laravel and Livewire, wouldn’t need help, right? Like, aren’t they the gurus who glide through code without breaking a sweat? Turns out… even seniors need a hand sometimes. Here’s why every Laravel senior could use another senior in their life—and maybe a few good laughs along the way.</p>
<h3>1. The “Senior” Myth: Masters of Laravel or Secret Googlers?</h3>
<p>If you think seniors know it all, let’s debunk that myth. Just picture this: a “seasoned” developer with ten years in Laravel who’s secretly searching, “why is my Livewire component loading three times?” Yep, they’re Googling, just like everyone else. Sometimes, a senior needs a senior just to swap “war stories” and realize they’re all just making it up as they go along.</p>
<blockquote>
<p>A senior developer is just a junior with a decade of Stack Overflow tabs open.</p>
</blockquote>
<h3>2. Livewire Mysteries: When “Reactive” Gets Too Real</h3>
<p>Livewire might be magical, but sometimes it’s just plain confusing. One minute you’re building a clean component, and the next, you’re asking yourself, “Why is this thing alive in every browser tab?” This is where another senior steps in, nodding knowingly and sharing that one trick they learned three projects ago.</p>
<blockquote>
<p>Livewire’s reactivity: where one refresh turns into a chain reaction, and you’ve started a browser revolution.</p>
</blockquote>
<h3>3. Middleware Mania: A Journey into the Layers</h3>
<p>One of the rites of passage for any Laravel developer is wrangling with middleware. But even seniors get stuck in that middleware labyrinth! When a simple route suddenly takes a trip down Middleware Lane, even the pros need someone to guide them out. Because let’s face it, sometimes even the best seniors get tangled up in their own webs.</p>
<blockquote>
<p>A senior without backup is like a Laravel route without middleware… eventually, you’re exposed</p>
</blockquote>
<h3>4. Package Wonderland: New, Shiny, and Confusing</h3>
<p>Every Laravel senior knows the joy of finding a shiny new package. And then comes the installation… “Wait, this isn’t working like the docs said!” This is the moment when having another senior’s input makes all the difference, turning “What is going on?” into, “Oh, let’s try this clever hack instead!”</p>
<blockquote>
<p>Package installs are a thrill ride: up, up, and then… down into the rabbit hole of dependencies.</p>
</blockquote>
<h3>5. Even the Pros Love Fresh Perspectives</h3>
<p>Laravel’s ecosystem is vast, and Livewire makes it exciting—but sometimes tricky. Having another senior, or even a keen junior, brings in fresh perspectives. Together, they can solve problems faster and maybe even discover new ways of doing things (or at least share a laugh over what <em>doesn’t</em> work!).</p>
<blockquote>
<p>The best seniors never stop learning—and occasionally, they even ask juniors for the <strong>latest shortcut</strong>.</p>
</blockquote>
<hr>
<p><strong>Final Thought</strong>: Even in the world of Laravel and Livewire, a senior benefits from having another senior around. So here’s to all the developers, from juniors to seniors—may we all keep learning, laughing, and Googling together!</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Dynamic Service Container Tagging for Runtime Logic Switching]]></title>
            <link>https://utsavsomaiya.in/articles/dynamic-service-container-tagging-runtime-logic-switching</link>
            <guid>https://utsavsomaiya.in/articles/dynamic-service-container-tagging-runtime-logic-switching</guid>
            <pubDate>Sun, 17 Nov 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>What is it?
Did you know that Laravel’s Service Container supports <strong>tagging</strong> for grouping multiple implementations of an interface or class? While tagging itself is documented, here’s the twist:</p>
<p>You can use <strong>dynamic tagging and runtime resolution</strong> to select implementations on the fly, making your services incredibly flexible without hardcoding anything.</p>
<h3>The Hack</h3>
<ol>
<li><strong>Define a Base Interface</strong></li>
</ol>
<p>Let’s say you have an interface for payment gateways:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">namespace</span><span style="color:#24292E"> </span><span style="color:#6F42C1">App\Contracts</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D73A49">interface</span><span style="color:#24292E"> </span><span style="color:#6F42C1">PaymentGateway</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">    </span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">process</span><span style="color:#24292E">($amount);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">namespace</span><span style="color:#D6DEEB"> App\Contracts;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#C792EA">interface</span><span style="color:#D6DEEB"> PaymentGateway</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">process</span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$amount</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<ol start="2">
<li><strong>Create Multiple Implementations</strong></li>
</ol>
<p>Define a couple of implementations for this interface:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">namespace</span><span style="color:#24292E"> </span><span style="color:#6F42C1">App\Services\Payments</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Contracts\PaymentGateway</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D73A49">class</span><span style="color:#24292E"> </span><span style="color:#6F42C1">StripeGateway</span><span style="color:#24292E"> </span><span style="color:#D73A49">implements</span><span style="color:#24292E"> </span><span style="color:#6F42C1">PaymentGateway</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">    </span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">process</span><span style="color:#24292E">($amount)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">    {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">        </span><span style="color:#D73A49">return</span><span style="color:#24292E"> </span><span style="color:#032F62">"Processing {</span><span style="color:#24292E">$amount</span><span style="color:#032F62">} via Stripe!"</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">}</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#D73A49">class</span><span style="color:#24292E"> </span><span style="color:#6F42C1">PayPalGateway</span><span style="color:#24292E"> </span><span style="color:#D73A49">implements</span><span style="color:#24292E"> </span><span style="color:#6F42C1">PaymentGateway</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#24292E">    </span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">process</span><span style="color:#24292E">($amount)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#24292E">    {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#24292E">        </span><span style="color:#D73A49">return</span><span style="color:#24292E"> </span><span style="color:#032F62">"Processing {</span><span style="color:#24292E">$amount</span><span style="color:#032F62">} via PayPal!"</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">namespace</span><span style="color:#D6DEEB"> App\Services\Payments;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Contracts\</span><span style="color:#FFCB8B">PaymentGateway</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">implements</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">PaymentGateway</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">process</span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$amount</span><span style="color:#D9F5DD">)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">    {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">Processing {</span><span style="color:#BEC5D4">$amount</span><span style="color:#ECC48D">} via Stripe!</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">}</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">PayPalGateway</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">implements</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">PaymentGateway</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">process</span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$amount</span><span style="color:#D9F5DD">)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#D6DEEB">    {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">Processing {</span><span style="color:#BEC5D4">$amount</span><span style="color:#ECC48D">} via PayPal!</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<ol start="3">
<li><strong>Tag Services in a Service Provider</strong></li>
</ol>
<p>In your <code>AppServiceProvider</code>, tag these implementations dynamically:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Contracts\PaymentGateway</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Services\Payments\StripeGateway</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Services\Payments\PayPalGateway</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">register</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">    </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">app</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">bind</span><span style="color:#24292E">(</span><span style="color:#005CC5">StripeGateway</span><span style="color:#D73A49">::class</span><span style="color:#24292E">, </span><span style="color:#D73A49">fn</span><span style="color:#24292E"> () =&gt; </span><span style="color:#D73A49">new</span><span style="color:#24292E"> </span><span style="color:#005CC5">StripeGateway</span><span style="color:#24292E">());</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">    </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">app</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">bind</span><span style="color:#24292E">(</span><span style="color:#005CC5">PayPalGateway</span><span style="color:#D73A49">::class</span><span style="color:#24292E">, </span><span style="color:#D73A49">fn</span><span style="color:#24292E"> () =&gt; </span><span style="color:#D73A49">new</span><span style="color:#24292E"> </span><span style="color:#005CC5">PayPalGateway</span><span style="color:#24292E">());</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    </span><span style="color:#6A737D">// Dynamically tag both services</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">    </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">app</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">tag</span><span style="color:#24292E">([</span><span style="color:#005CC5">StripeGateway</span><span style="color:#D73A49">::class</span><span style="color:#24292E">, </span><span style="color:#005CC5">PayPalGateway</span><span style="color:#D73A49">::class</span><span style="color:#24292E">], </span><span style="color:#032F62">'payment_gateways'</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Contracts\</span><span style="color:#FFCB8B">PaymentGateway</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Services\Payments\</span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Services\Payments\</span><span style="color:#FFCB8B">PayPalGateway</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">register</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">app</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">bind</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#7FDBCA">new</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#D6DEEB">());</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">app</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">bind</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">PayPalGateway</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#7FDBCA">new</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">PayPalGateway</span><span style="color:#D6DEEB">());</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> Dynamically tag both services</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">app</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">tag</span><span style="color:#D6DEEB">([</span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">, </span><span style="color:#FFCB8B">PayPalGateway</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">], </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">payment_gateways</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<ol start="4">
<li><strong>Resolve Dynamically Based on Logic</strong></li>
</ol>
<p>Now you can resolve and switch between implementations at runtime based on dynamic conditions:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Contracts\Container\Container</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">getPaymentGateway</span><span style="color:#24292E">(</span><span style="color:#005CC5">Container</span><span style="color:#24292E"> $container, $preferredGateway)</span><span style="color:#D73A49">:</span><span style="color:#24292E"> </span><span style="color:#005CC5">PaymentGateway</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#24292E">    $gateways </span><span style="color:#D73A49">=</span><span style="color:#24292E"> $container</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">tagged</span><span style="color:#24292E">(</span><span style="color:#032F62">'payment_gateways'</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">    </span><span style="color:#D73A49">foreach</span><span style="color:#24292E"> ($gateways </span><span style="color:#D73A49">as</span><span style="color:#24292E"> $gateway) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">        </span><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#005CC5">get_class</span><span style="color:#24292E">($gateway) </span><span style="color:#D73A49">===</span><span style="color:#24292E"> $preferredGateway) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">            </span><span style="color:#D73A49">return</span><span style="color:#24292E"> $gateway;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">        }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#24292E">    </span><span style="color:#D73A49">throw</span><span style="color:#24292E"> </span><span style="color:#D73A49">new</span><span style="color:#24292E"> </span><span style="color:#005CC5">\Exception</span><span style="color:#24292E">(</span><span style="color:#032F62">"No gateway found for {</span><span style="color:#24292E">$preferredGateway</span><span style="color:#032F62">}"</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#24292E">}</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#6A737D">// Example usage</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#24292E">$gatewayClass </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#005CC5">\App\Services\Payments\StripeGateway</span><span style="color:#D73A49">::class</span><span style="color:#24292E">; </span><span style="color:#6A737D">// Could come from config or runtime logic</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#24292E">$gateway </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#6F42C1">getPaymentGateway</span><span style="color:#24292E">(</span><span style="color:#6F42C1">app</span><span style="color:#24292E">(), $gatewayClass);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#005CC5">echo</span><span style="color:#24292E"> $gateway</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">process</span><span style="color:#24292E">(</span><span style="color:#005CC5">100</span><span style="color:#24292E">); </span><span style="color:#6A737D">// Outputs: Processing 100 via Stripe!</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Contracts\Container\</span><span style="color:#FFCB8B">Container</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">getPaymentGateway</span><span style="color:#D9F5DD">(</span><span style="color:#FFCB8B">Container</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$container</span><span style="color:#D6DEEB">, </span><span style="color:#BEC5D4">$preferredGateway</span><span style="color:#D9F5DD">)</span><span style="color:#7FDBCA">:</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">PaymentGateway</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D6DEEB">    </span><span style="color:#BEC5D4">$gateways</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$container</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">tagged</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">payment_gateways</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">foreach</span><span style="color:#D6DEEB"> (</span><span style="color:#BEC5D4">$gateways</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">as</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$gateway</span><span style="color:#D6DEEB">) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">if</span><span style="color:#D6DEEB"> (</span><span style="color:#C5E478">get_class</span><span style="color:#D6DEEB">($</span><span style="color:#BEC5D4">gateway</span><span style="color:#D6DEEB">) </span><span style="color:#C792EA">===</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$preferredGateway</span><span style="color:#D6DEEB">) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$gateway</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">        }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">throw</span><span style="color:#D6DEEB"> </span><span style="color:#7FDBCA">new</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">\Exception</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">No gateway found for {</span><span style="color:#BEC5D4">$preferredGateway</span><span style="color:#ECC48D">}</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#D6DEEB">}</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#637777">//</span><span style="color:#637777"> Example usage</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#BEC5D4">$gatewayClass</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> \App\Services\Payments\</span><span style="color:#FFCB8B">StripeGateway</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">; </span><span style="color:#637777">//</span><span style="color:#637777"> Could come from config or runtime logic</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#BEC5D4">$gateway</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">getPaymentGateway</span><span style="color:#D6DEEB">(</span><span style="color:#82AAFF">app</span><span style="color:#D6DEEB">(),</span><span style="color:#82AAFF"> </span><span style="color:#D6DEEB">$</span><span style="color:#BEC5D4">gatewayClass</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#C5E478">echo</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$gateway</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">process</span><span style="color:#D6DEEB">(</span><span style="color:#F78C6C">100</span><span style="color:#D6DEEB">); </span><span style="color:#637777">//</span><span style="color:#637777"> Outputs: Processing 100 via Stripe!</span></div></code></pre></div>
<ol start="5">
<li><strong>Bonus Hack: Auto-Tag Based on Folder Scanning</strong></li>
</ol>
<p>Let’s take it a step further and auto-tag classes in a folder:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\File</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">register</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#24292E">    $paymentServices </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#6F42C1">collect</span><span style="color:#24292E">(</span><span style="color:#005CC5">File</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">allFiles</span><span style="color:#24292E">(</span><span style="color:#6F42C1">app_path</span><span style="color:#24292E">(</span><span style="color:#032F62">'Services/Payments'</span><span style="color:#24292E">)))</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">        </span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">map</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E"> ($file) =&gt; </span><span style="color:#032F62">'App</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Services</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Payments</span><span style="color:#005CC5">\\</span><span style="color:#032F62">'</span><span style="color:#24292E"> </span><span style="color:#D73A49">.</span><span style="color:#24292E"> $file</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">getFilenameWithoutExtension</span><span style="color:#24292E">())</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">        </span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">filter</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E"> ($class) =&gt; </span><span style="color:#005CC5">class_exists</span><span style="color:#24292E">($class))</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">        </span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">each</span><span style="color:#24292E">(</span><span style="color:#D73A49">fn</span><span style="color:#24292E"> ($class) =&gt; </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">app</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">bind</span><span style="color:#24292E">($class, </span><span style="color:#D73A49">fn</span><span style="color:#24292E"> () =&gt; </span><span style="color:#D73A49">new</span><span style="color:#24292E"> $class()));</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">app</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">tag</span><span style="color:#24292E">($paymentServices</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">all</span><span style="color:#24292E">(), </span><span style="color:#032F62">'payment_gateways'</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">File</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">register</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D6DEEB">    </span><span style="color:#BEC5D4">$paymentServices</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">collect</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">File</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">allFiles</span><span style="color:#D6DEEB">(</span><span style="color:#82AAFF">app_path</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Services/Payments</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">)))</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">map</span><span style="color:#D6DEEB">(</span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$file</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">App</span><span style="color:#F78C6C">\\</span><span style="color:#ECC48D">Services</span><span style="color:#F78C6C">\\</span><span style="color:#ECC48D">Payments</span><span style="color:#F78C6C">\\</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB"> </span><span style="color:#7FDBCA">.</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$file</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">getFilenameWithoutExtension</span><span style="color:#D6DEEB">())</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">filter</span><span style="color:#D6DEEB">(</span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$class</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#C5E478">class_exists</span><span style="color:#D6DEEB">($</span><span style="color:#BEC5D4">class</span><span style="color:#D6DEEB">))</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">each</span><span style="color:#D6DEEB">(</span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$class</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">app</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">bind</span><span style="color:#D6DEEB">(</span><span style="color:#BEC5D4">$class</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#7FDBCA">new</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$class</span><span style="color:#D6DEEB">()));</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#BEC5D4">app</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">tag</span><span style="color:#D6DEEB">(</span><span style="color:#BEC5D4">$paymentServices</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">all</span><span style="color:#D6DEEB">(), </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">payment_gateways</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>Now, any new class in <code>App\Services\Payments</code> is automatically tagged and ready to use.</p>
<img alt="Diagram" loading="lazy" width="2954" height="2070" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdiagram.37d49159.png&amp;w=3840&amp;q=75 1x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdiagram.37d49159.png&amp;w=3840&amp;q=75">]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Fast database queries are not always better]]></title>
            <link>https://utsavsomaiya.in/articles/fast-database-queries-are-always-not-better</link>
            <guid>https://utsavsomaiya.in/articles/fast-database-queries-are-always-not-better</guid>
            <pubDate>Thu, 24 Aug 2023 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>You probably think fast database queries are good. You also probably think slow database queries are bad. On top of all of these "thinks" you have about database queries - there is a certain Laravel method that, if you have seen it, you probably think you understand…but there is a chance you don’t.</p>
<p>The last one is likely my fault; I am sorry.</p>
<p>Let’s challenge your thinking on queries and see if we can’t clear up this Laravel function mess I have put us in.</p>
<h2>Are slow database queries bad?</h2>
<p>Some queries are just inherently slow and as optimized as they are gonna get. That is fine, but...</p>
<p>I think we can agree that slow queries are generally bad. Maybe "bad" isn’t the right word. Perhaps "not ideal" is better.</p>
<p>Slow database queries are not ideal. Yea. That's better.</p>
<p>But how do we even define "slow"?</p>
<p>We could compare two queries, e.g., a 50ms query verses a 2s query. In this case the 2 second query is slow (without knowing any context about the query).</p>
<p>Alternatively, instead of comparing two queries, we might explicitly define what a "slow" query is within our system by setting an explicit threshold via the <a href="https://dev.mysql.com/doc/refman/8.0/en/slow-query-log.html">Slow Query Log</a> feature of the database. This allows us to operationalise what we consider a slow query.</p>
<p>Why don’t we set our imaginary slow query threshold to 1 second. Anything over 1 second we will classify as slow, for the purpose of the post.</p>
<p>Our slow query log will now record queries over 1 second. If the logs are filling up, we know we have slow queries and can try to address them.</p>
<p>Well that wasn’t all too exciting. So let’s talk about fast database queries…</p>
<h2>Are fast queries good?</h2>
<p>Are they? What makes them good? In what context are we talking?</p>
<p>I’d have a guess and say you feel they are good because they indicate your application is fast, at least when it comes to querying the database.</p>
<p>In isolation: fast database queries are good.</p>
<p>But I don't deal with queries in isolation. I work on web apps that have rich interactions with potentially multiple queries happening within a single HTTP request lifecycle, queued job, or artisan command.</p>
<p>If we were to use comparison as our measure again: a HTTP request that queries the database for 5ms is better than a HTTP request that queries the database for 1.5 seconds, right?</p>
<p>I think it is, in regards to resource usage at least.</p>
<p>What if I make a HTTP request and there are no logs in my slow query log, is that good?</p>
<p>I don’t think so. I don’t think it’s bad, but I don’t think it’s evidence of "good" either.</p>
<p>After all, what information do we actually have with an empty slow query log?</p>
<p>We know that the HTTP request did not perform any queries over 1 second. This sounds good, but it isn’t enough information to work with.</p>
<p>What if our HTTP request executed the following code. Forgive the extreme example.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Models\User</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">$endAt </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#6F42C1">now</span><span style="color:#24292E">()</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">addSeconds</span><span style="color:#24292E">(</span><span style="color:#005CC5">20</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D73A49">while</span><span style="color:#24292E"> ($endAt</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">isFuture</span><span style="color:#24292E">()) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">    </span><span style="color:#005CC5">User</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">first</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Models\</span><span style="color:#FFCB8B">User</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#BEC5D4">$endAt</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">now</span><span style="color:#D6DEEB">()</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">addSeconds</span><span style="color:#D6DEEB">(</span><span style="color:#F78C6C">20</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#C792EA">while</span><span style="color:#D6DEEB"> (</span><span style="color:#BEC5D4">$endAt</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">isFuture</span><span style="color:#D6DEEB">()) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">User</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">first</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>The above code executes a very fast database query, however it executes the query in a non-stop loop for 20 seconds. Of course this is a contrived example, but I've certainly worked in applications where, for example, checking feature flags made hundreds, and sometimes thousands, of "fast" database queries throughout a single HTTP request.</p>
<p>If the above code was executed within a HTTP request to my application, there are a few facts that reveal themselves:</p>
<ol>
<li>I am a psychopath.</li>
<li>My slow query log will be empty.</li>
</ol>
<p>These queries are fast; These queries are not <em>good</em></p>
<p>So fast queries are not indicative of "good" in this particular context. The slow query log only goes so far.</p>
<p>What I really want to do, in order to make my HTTP requests fast, is to spend less time in the database for my overall request. I care about the "cumulative query time" for the request.</p>
<p>If I make one 2 second query or four 0.5 second queries, they both make my HTTP request slower by 2 seconds and, from an end-user perspective, are both just as slow as each other.</p>
<p>So what can we do? Well, now I'm gonna reach for my sharp hammer: Laravel.</p>
<h2>Measuring query time with Laravel</h2>
<p>I’m gonna show you a thing. This isn’t the thing. This is a thing, and a thing to cover, but it isn’t the thing. So I’ll try and be brief.</p>
<p>Laravel has a way to listen for queries and check their duration. We could, for example, emulate the slow query log with something like the following:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Database\Events\QueryExecuted</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Event</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Log</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#005CC5">Event</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">listen</span><span style="color:#24292E">(</span><span style="color:#005CC5">QueryExecuted</span><span style="color:#24292E">, </span><span style="color:#D73A49">function</span><span style="color:#24292E"> (</span><span style="color:#005CC5">QueryExecuted</span><span style="color:#24292E"> $event) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">    </span><span style="color:#D73A49">if</span><span style="color:#24292E"> ($event</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">time </span><span style="color:#D73A49">&gt;</span><span style="color:#24292E"> </span><span style="color:#005CC5">1000</span><span style="color:#24292E">) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">        </span><span style="color:#005CC5">Log</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">info</span><span style="color:#24292E">(</span><span style="color:#032F62">'Slow query detected.'</span><span style="color:#24292E">, [</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">            </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">        ]);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">});</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Database\Events\</span><span style="color:#FFCB8B">QueryExecuted</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Event</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Log</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C5E478">Event</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">listen</span><span style="color:#D6DEEB">(</span><span style="color:#82AAFF">QueryExecuted</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#FFCB8B">QueryExecuted</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$event</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">if</span><span style="color:#D6DEEB"> (</span><span style="color:#BEC5D4">$event</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#BEC5D4">time</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">&gt;</span><span style="color:#D6DEEB"> </span><span style="color:#F78C6C">1000</span><span style="color:#D6DEEB">) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">        </span><span style="color:#FFCB8B">Log</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">info</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Slow query detected.</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, [</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">            </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">        ]);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">});</span></div></code></pre></div>
<p>If any individual query made by Laravel is over the 1 second threshold it will log <code>"Slow query detected."</code> to the application log. If 5 queries in a single HTTP request all take over 1 second it will log this message 5 times.</p>
<p>This does not give us anything new and moving it to Laravel is fine, but not ideal.</p>
<p>But knowing this technique is relevant to help us differentiate what we are about to talk about.</p>
<h2>Measuring cumulative query time with Laravel</h2>
<p>A little while ago I added a method to Laravel. You might have seen this method:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Database\Connection</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\DB</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#005CC5">DB</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">whenQueryingForLongerThan</span><span style="color:#24292E">(</span><span style="color:#005CC5">1000</span><span style="color:#24292E">, </span><span style="color:#D73A49">function</span><span style="color:#24292E"> (</span><span style="color:#005CC5">Connection</span><span style="color:#24292E"> $connection) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">    </span><span style="color:#005CC5">Log</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">info</span><span style="color:#24292E">(</span><span style="color:#032F62">'Queries collectively took longer than 1 second.'</span><span style="color:#24292E">, [</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">        </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">    ]);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#24292E">});</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Database\</span><span style="color:#FFCB8B">Connection</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">DB</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#FFCB8B">DB</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">whenQueryingForLongerThan</span><span style="color:#D6DEEB">(</span><span style="color:#F78C6C">1000</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#FFCB8B">Connection</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$connection</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">Log</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">info</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Queries collectively took longer than 1 second.</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, [</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">        </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">    ]);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#D6DEEB">});</span></div></code></pre></div>
<p>You might be forgiven for assuming that this handler and the previous query log emulation example were the same, i.e., if a query takes longer than 1 second to execute than the provided closure is called.</p>
<p>You would be forgiven because multiple people have told me they thought that is what it did.</p>
<p>But they are not the same. The first event listener example only considers a single query in isolation, while this new handler considers the context of the entire HTTP request.</p>
<p>To show the difference, let’s register both of these in our imaginary application’s service provider. We’ll continue to use 1 second for our logging threshold.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Database\Connection</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Database\Events\QueryExecuted</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Auth</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\DB</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Event</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Log</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Request</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#6A737D">/*</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#6A737D"> * Log when any query exceeds one second in duration.</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#6A737D"> */</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#005CC5">Event</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">listen</span><span style="color:#24292E">(</span><span style="color:#005CC5">QueryExecuted</span><span style="color:#24292E">, </span><span style="color:#D73A49">function</span><span style="color:#24292E"> (</span><span style="color:#005CC5">QueryExecuted</span><span style="color:#24292E"> $event) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#24292E">    </span><span style="color:#D73A49">if</span><span style="color:#24292E"> ($event</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">time </span><span style="color:#D73A49">&gt;</span><span style="color:#24292E"> </span><span style="color:#005CC5">1000</span><span style="color:#24292E">) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#24292E">       </span><span style="color:#005CC5">Log</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">info</span><span style="color:#24292E">(</span><span style="color:#032F62">'Query took longer than 1 second.'</span><span style="color:#24292E">, [</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#24292E">           </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#24292E">       ]);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#24292E">});</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#6A737D">/*</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#6A737D"> * Log when all queries collectivly exceed one second in duration.</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#6A737D"> */</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#005CC5">DB</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">whenQueryingForLongerThan</span><span style="color:#24292E">(</span><span style="color:#005CC5">1000</span><span style="color:#24292E">, </span><span style="color:#D73A49">function</span><span style="color:#24292E"> (</span><span style="color:#005CC5">Connection</span><span style="color:#24292E"> $connection) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#24292E">    </span><span style="color:#005CC5">Log</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">info</span><span style="color:#24292E">(</span><span style="color:#032F62">'Queries collectively took longer than 1 second.'</span><span style="color:#24292E">, [</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#24292E">        </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#24292E">    ]);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#24292E">});</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Database\</span><span style="color:#FFCB8B">Connection</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Database\Events\</span><span style="color:#FFCB8B">QueryExecuted</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Auth</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">DB</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Event</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Log</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Request</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#637777">/*</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#637777"> * Log when any query exceeds one second in duration.</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#637777"> </span><span style="color:#637777">*/</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#C5E478">Event</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">listen</span><span style="color:#D6DEEB">(</span><span style="color:#82AAFF">QueryExecuted</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#FFCB8B">QueryExecuted</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$event</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">if</span><span style="color:#D6DEEB"> (</span><span style="color:#BEC5D4">$event</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#BEC5D4">time</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">&gt;</span><span style="color:#D6DEEB"> </span><span style="color:#F78C6C">1000</span><span style="color:#D6DEEB">) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#D6DEEB">       </span><span style="color:#FFCB8B">Log</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">info</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Query took longer than 1 second.</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, [</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#D6DEEB">           </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#D6DEEB">       ]);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#D6DEEB">});</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#637777">/*</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#637777"> * Log when all queries collectivly exceed one second in duration.</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#637777"> </span><span style="color:#637777">*/</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#FFCB8B">DB</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">whenQueryingForLongerThan</span><span style="color:#D6DEEB">(</span><span style="color:#F78C6C">1000</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">(</span><span style="color:#FFCB8B">Connection</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$connection</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">Log</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">info</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Queries collectively took longer than 1 second.</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, [</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#D6DEEB">        </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#D6DEEB">    ]);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#D6DEEB">});</span></div></code></pre></div>
<p>Then we will make a HTTP request to the endpoint with our terrible code again. I've duplicated it here for your personal pain and suffering - and as a friendly reminder.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Models\User</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">$endAt </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#6F42C1">now</span><span style="color:#24292E">()</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">addSeconds</span><span style="color:#24292E">(</span><span style="color:#005CC5">20</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D73A49">while</span><span style="color:#24292E"> ($endAt</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">isFuture</span><span style="color:#24292E">()) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">    </span><span style="color:#005CC5">User</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">first</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Models\</span><span style="color:#FFCB8B">User</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#BEC5D4">$endAt</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">now</span><span style="color:#D6DEEB">()</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">addSeconds</span><span style="color:#D6DEEB">(</span><span style="color:#F78C6C">20</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#C792EA">while</span><span style="color:#D6DEEB"> (</span><span style="color:#BEC5D4">$endAt</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">isFuture</span><span style="color:#D6DEEB">()) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">User</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">first</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>Now something interesting will happen when this HTTP request is finished:</p>
<ol>
<li>My slow query log will be empty.</li>
<li>Our application’s log will not contain any <code>"Slow query detected."</code> entries</li>
<li>Our application log will, however, contain a single <code>"Queries collectively took longer than 1 second."</code> entry.</li>
</ol>
<p>This is because the <code>whenQueryingForLongerThan</code> feature will keep track of all queries made during a single HTTP request lifecycle. If many fast queries are made that, when added together, take longer than one second the closure will be called and it will only ever be called once per HTTP request lifecycle.</p>
<p>This allows us to detect and log when many fast queries cause our HTTP requests to be slow 🎉</p>
<p>See! Fast queries can be bad!</p>
<p>This feature doesn’t just work for HTTP requests. It also works for queued jobs, where the closure is called once per job lifecycle.</p>
<p>It’s pretty neat, but I always felt it needed a better name to make it more obvious how it deviates from the alternative <code>QueryExecuted</code> event listener set up.</p>
<p>So that’s what this post is. This post is, in its entirety, the new method name.</p>
<p>Remember that none of this is a replacement for the database’s slow query log. The database's slow query log is an important tool to dive into and learn about.</p>
<blockquote>
<p>Fun fact: the MySQL slow query log limit is 365 days. It’s like they knew I might be crafting queries 😆</p>
</blockquote>
<h3>Further reading</h3>
<ul>
<li><a href="https://laravel.com/docs/master/database#monitoring-cumulative-query-time"><code>DB::whenQueryingForLongerThan</code> documentation</a></li>
<li><a href="https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html">MySQL slow query log documentation</a></li>
</ul>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[From Developer to Senior Manager: Debugging My Career Path]]></title>
            <link>https://utsavsomaiya.in/articles/from-developer-to-senior-manager</link>
            <guid>https://utsavsomaiya.in/articles/from-developer-to-senior-manager</guid>
            <pubDate>Sun, 15 Sep 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>As a developer, life was simple. Write code, fix bugs, deploy. Rinse and repeat. But somewhere along the way, I leveled up—not in a video game sense (although I wish)—but to something called a “senior manager with developer responsibilities.” Let me walk you through my journey from debugging code to, well… debugging humans.</p>
<img alt="" loading="lazy" width="1456" height="816" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdeveloper-code-at-night.34c20140.jpg&amp;w=1920&amp;q=75 1x, /_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdeveloper-code-at-night.34c20140.jpg&amp;w=3840&amp;q=75 2x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fdeveloper-code-at-night.34c20140.jpg&amp;w=3840&amp;q=75">
<h2>Stage 1: Developer Life – All Code, All Day</h2>
<p>Back in the good ol’ days, I was living and breathing code. My world was filled with Tailwind CSS, Alpine.js, Vue.js, Laravel—you name it. <strong>If there was an acronym, I probably worked with it.</strong></p>
<p>Every day I was building features like:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">buildCoolFeature</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">    </span><span style="color:#6A737D">// Logic here to make users happy</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#24292E">    </span><span style="color:#D73A49">return</span><span style="color:#24292E"> </span><span style="color:#6F42C1">success</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">buildCoolFeature</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> Logic here to make users happy</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">success</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>I didn’t care much about meetings or management; just give me a coffee, and I could ship code like nobody’s business. Life was good!</p>
<p>But then… things started to change.</p>
<h2>Stage 2: My First Intern – The Mentor Awakens</h2>
<p>The real turning point came when I was asked to mentor an intern. Intern? Like, you want me to explain what I do… to someone else? Oh boy. But I took the challenge head-on and suddenly found myself explaining complex code like:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D">// What I told my intern:</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#24292E">$coffee </span><span style="color:#D73A49">=</span><span style="color:#24292E"> </span><span style="color:#6F42C1">makeCoffee</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#6A737D">// What they heard:</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#005CC5">💡☕️🤯</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">//</span><span style="color:#637777"> What I told my intern:</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#BEC5D4">$coffee</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">makeCoffee</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#637777">//</span><span style="color:#637777"> What they heard:</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#82AAFF">💡☕️🤯</span></div></code></pre></div>
<p>Surprisingly, mentoring wasn’t so bad. I mean, yeah, it was like teaching a toddler to code at times, but seeing them grow into actual developers made me feel like a proud parent. The debugging sessions were goldmines of life lessons… and occasional disasters.</p>
<h2>Stage 3: The Promotion – More Responsibilities, More Coffee</h2>
<p>Then one day, they threw the big title at me: <strong>Senior Manager with Developer Responsibilities</strong>. Suddenly, I wasn’t just responsible for my own code anymore. Nope, now I had to manage <em>other people’s</em> code. Yikes!</p>
<p>Meetings started creeping into my calendar like unexpected bugs in production:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D">// Old daily schedule:</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#24292E">$tasks </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [ </span><span style="color:#032F62">'coding'</span><span style="color:#24292E">, </span><span style="color:#032F62">'debugging'</span><span style="color:#24292E">, </span><span style="color:#032F62">'fixing things'</span><span style="color:#24292E"> ];</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#6A737D">// New daily schedule:</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">$tasks </span><span style="color:#D73A49">=</span><span style="color:#24292E"> [ </span><span style="color:#032F62">'meetings'</span><span style="color:#24292E">, </span><span style="color:#032F62">'more meetings'</span><span style="color:#24292E">, </span><span style="color:#032F62">'asking devs why it’s still broken'</span><span style="color:#24292E"> ];</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">//</span><span style="color:#637777"> Old daily schedule:</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#BEC5D4">$tasks</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> [ </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">coding</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">debugging</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">fixing things</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB"> ];</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#637777">//</span><span style="color:#637777"> New daily schedule:</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#BEC5D4">$tasks</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">=</span><span style="color:#D6DEEB"> [ </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">meetings</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">more meetings</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">asking devs why it’s still broken</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB"> ];</span></div></code></pre></div>
<h2>Stage 4: Team Management – The Art of Debugging People</h2>
<p>Turns out, managing a team isn’t that different from writing code. You just replace semicolons with people’s emotions.</p>
<p>One day, your junior dev is super productive, smashing out PRs. The next day, they're asking you what “git” is. So, I had to learn how to be <em>flexible</em>:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D">// New responsibilities as a manager:</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D73A49">if</span><span style="color:#24292E"> (</span><span style="color:#6F42C1">devsAreStuck</span><span style="color:#24292E">()) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">    </span><span style="color:#6A737D">// Try turning it off and on again (the dev, not the code)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#24292E">    </span><span style="color:#6F42C1">giveEncouragement</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">} </span><span style="color:#D73A49">else</span><span style="color:#24292E"> {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">    </span><span style="color:#6A737D">// When things are magically working</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">    </span><span style="color:#6F42C1">justSmileAndNod</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">//</span><span style="color:#637777"> New responsibilities as a manager:</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#C792EA">if</span><span style="color:#D6DEEB"> (</span><span style="color:#82AAFF">devsAreStuck</span><span style="color:#D6DEEB">()) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> Try turning it off and on again (the dev, not the code)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">    </span><span style="color:#82AAFF">giveEncouragement</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">} </span><span style="color:#C792EA">else</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> When things are magically working</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">    </span><span style="color:#82AAFF">justSmileAndNod</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<h2>Stage 5: Balancing Code and Chaos – The Daily Grind</h2>
<p>Balancing coding with management is like trying to deploy on a Friday—risky but sometimes necessary. Some days, I’m deep in code. Other days, I’m figuring out why half the team’s in a Slack battle over the most efficient way to name a variable.</p>
<p>As a senior manager, it’s my job to make sure the team runs smoothly:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">keepTeamHappy</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">    </span><span style="color:#6A737D">// Main function for a successful team</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#24292E">    </span><span style="color:#D73A49">while</span><span style="color:#24292E"> (</span><span style="color:#005CC5">teamProductivity</span><span style="color:#24292E"> </span><span style="color:#D73A49">&lt;</span><span style="color:#24292E"> </span><span style="color:#005CC5">100</span><span style="color:#24292E">) {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">        </span><span style="color:#6F42C1">encourage</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">        </span><span style="color:#6F42C1">drinkCoffee</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">        </span><span style="color:#6F42C1">debug</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">9</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">keepTeamHappy</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> Main function for a successful team</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">while</span><span style="color:#D6DEEB"> (</span><span style="color:#82AAFF">teamProductivity</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">&lt;</span><span style="color:#D6DEEB"> </span><span style="color:#F78C6C">100</span><span style="color:#D6DEEB">) {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">        </span><span style="color:#82AAFF">encourage</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">        </span><span style="color:#82AAFF">drinkCoffee</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">        </span><span style="color:#82AAFF">debug</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">9</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>The trick is staying connected to both worlds. I still code, mentor, and review PRs, but now I also navigate the tricky waters of <em>people</em> management.</p>
<h2>Final Stage: Lessons Learned – Lead with Humor, and Maybe Coffee</h2>
<p>Here’s what I’ve learned on this journey from developer to senior manager:</p>
<ol>
<li><strong>Code is easy, people are hard:</strong> Debugging a null pointer error? Easy. Figuring out why Bob from QA keeps using tabs instead of spaces? That’s the real challenge.</li>
<li><strong>Mentoring is like pair programming, but with emotions:</strong> Explaining code to someone new is the best way to remind yourself how little you understand. But it’s also incredibly rewarding.</li>
<li><strong>Coffee powers everything:</strong> Whether it’s fixing bugs or attending meetings, coffee is the fuel. Seriously, it should come with the title.</li>
<li><strong>Take a break, laugh at yourself:</strong> This job can be stressful, so it’s important to laugh—at your mistakes, at your team’s memes, and definitely at the inevitable “works on my machine” excuses.</li>
</ol>
<hr>
<p><strong>Conclusion:</strong> Becoming a senior manager with developer responsibilities has been a wild ride. From writing code to mentoring interns and leading a team, it’s been a journey of growth, patience, and, yes, a whole lot of coffee.</p>
<p>So, if you’re thinking about stepping into management, just remember: it’s like being a developer… except now you’re debugging humans, too.</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Stop Click Hijacking: Mastering wire:navigate with Alpine Dialogs]]></title>
            <link>https://utsavsomaiya.in/articles/prevent-unintended-navigation-when-using-wire-navigate</link>
            <guid>https://utsavsomaiya.in/articles/prevent-unintended-navigation-when-using-wire-navigate</guid>
            <pubDate>Wed, 05 Nov 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>You build a card-style CTA.
It’s clickable. It should navigate when tapped.</p>
<p>Inside that card, you also add a tiny button to open a dialog.</p>
<p>Here’s the thing:
because the whole card is wrapped in a navigation click, that little button doesn’t stand a chance.
Users try to open the dialog… and boom. they’re already on the next page.</p>
<p>I didn’t go hunting strangers or asking every developer forum to bless me.
I opened the docs and figured it out.</p>
<h3><a href="https://livewire.laravel.com/docs/3.x/navigate#manually-visiting-a-new-page">Livewire Navigation Docs</a></h3>
<h2>Before: The Unwanted Navigation</h2>
<p>Typical structure:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">a</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#24292E">    </span><span style="color:#6F42C1">wire</span><span style="color:#24292E">:</span><span style="color:#005CC5">navigate</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#24292E">    </span><span style="color:#005CC5">href</span><span style="color:#D73A49">=</span><span style="color:#032F62">"{{ route('target.route', ['param' =&gt; </span><span style="color:#24292E">$param</span><span style="color:#D73A49">-&gt;</span><span style="color:#24292E">id</span><span style="color:#032F62">]) }}"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#24292E">    </span><span style="color:#005CC5">x</span><span style="color:#D73A49">-</span><span style="color:#005CC5">data</span><span style="color:#D73A49">=</span><span style="color:#032F62">"{ dialogOpen: false }"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#24292E">    </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"block rounded-2xl border border-zinc-200 p-5"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">    </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">div</span><span style="color:#24292E"> </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"flex items-start justify-between gap-4"</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">        </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">div</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">            </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">h3</span><span style="color:#24292E"> </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"text-lg font-semibold"</span><span style="color:#D73A49">&gt;</span><span style="color:#005CC5">Action</span><span style="color:#24292E"> </span><span style="color:#005CC5">Title</span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">h3</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">            </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">p</span><span style="color:#24292E"> </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"mt-1 text-sm text-zinc-600"</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">                </span><span style="color:#005CC5">Tap</span><span style="color:#24292E"> </span><span style="color:#005CC5">anywhere</span><span style="color:#24292E"> </span><span style="color:#005CC5">on</span><span style="color:#24292E"> </span><span style="color:#005CC5">the</span><span style="color:#24292E"> </span><span style="color:#005CC5">card</span><span style="color:#24292E"> </span><span style="color:#005CC5">to</span><span style="color:#24292E"> </span><span style="color:#D73A49">continue</span><span style="color:#D73A49">.</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">            </span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">p</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#24292E">        </span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">div</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#24292E">        </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">button</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#24292E">            </span><span style="color:#005CC5">type</span><span style="color:#D73A49">=</span><span style="color:#032F62">"button"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#24292E">            </span><span style="color:#005CC5">x</span><span style="color:#D73A49">-</span><span style="color:#005CC5">on</span><span style="color:#24292E">:</span><span style="color:#005CC5">click</span><span style="color:#D73A49">=</span><span style="color:#032F62">"dialogOpen = true"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#24292E">            </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"inline-flex h-9 w-9 items-center justify-center rounded-full border"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#24292E">        </span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#24292E">            </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">x</span><span style="color:#D73A49">-</span><span style="color:#005CC5">lucide</span><span style="color:#D73A49">-</span><span style="color:#005CC5">info</span><span style="color:#24292E"> </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"h-4 w-4"</span><span style="color:#24292E"> </span><span style="color:#D73A49">/&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#24292E">        </span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">button</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#24292E">    </span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">div</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#24292E">    </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">div</span><span style="color:#24292E"> </span><span style="color:#005CC5">x</span><span style="color:#D73A49">-</span><span style="color:#005CC5">show</span><span style="color:#D73A49">=</span><span style="color:#032F62">"dialogOpen"</span><span style="color:#24292E"> </span><span style="color:#D73A49">class=</span><span style="color:#032F62">"dialog-panel"</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#24292E">        </span><span style="color:#D73A49">&lt;</span><span style="color:#005CC5">p</span><span style="color:#D73A49">&gt;</span><span style="color:#005CC5">Extra</span><span style="color:#24292E"> </span><span style="color:#005CC5">context</span><span style="color:#24292E"> </span><span style="color:#D73A49">for</span><span style="color:#24292E"> </span><span style="color:#005CC5">the</span><span style="color:#24292E"> </span><span style="color:#005CC5">user</span><span style="color:#D73A49">.</span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">p</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#24292E">    </span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">div</span><span style="color:#D73A49">&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#D73A49">&lt;/</span><span style="color:#005CC5">a</span><span style="color:#D73A49">&gt;</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">a</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#D6DEEB">    wire:</span><span style="color:#82AAFF">navigate</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D6DEEB">    </span><span style="color:#82AAFF">href</span><span style="color:#C792EA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">{{ route('target.route', ['param' =&gt; </span><span style="color:#BEC5D4">$param</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#BEC5D4">id</span><span style="color:#ECC48D">]) }}</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D6DEEB">    </span><span style="color:#82AAFF">x</span><span style="color:#C792EA">-</span><span style="color:#82AAFF">data</span><span style="color:#C792EA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">{ dialogOpen: false }</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">block rounded-2xl border border-zinc-200 p-5</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">div</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">flex items-start justify-between gap-4</span><span style="color:#D9F5DD">"</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">div</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">h3</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">text-lg font-semibold</span><span style="color:#D9F5DD">"</span><span style="color:#C792EA">&gt;</span><span style="color:#82AAFF">Action</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">Title</span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">h3</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">p</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">mt-1 text-sm text-zinc-600</span><span style="color:#D9F5DD">"</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">                </span><span style="color:#82AAFF">Tap</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">anywhere</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">on</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">the</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">card</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">to</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">continue</span><span style="color:#7FDBCA">.</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">p</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">div</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">button</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#D6DEEB">            </span><span style="color:#82AAFF">type</span><span style="color:#C792EA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">button</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#D6DEEB">            </span><span style="color:#82AAFF">x</span><span style="color:#C792EA">-</span><span style="color:#82AAFF">on</span><span style="color:#D6DEEB">:</span><span style="color:#82AAFF">click</span><span style="color:#C792EA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">dialogOpen = true</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">inline-flex h-9 w-9 items-center justify-center rounded-full border</span><span style="color:#D9F5DD">"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#D6DEEB">            </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">x</span><span style="color:#C792EA">-</span><span style="color:#82AAFF">lucide</span><span style="color:#C792EA">-</span><span style="color:#82AAFF">info</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">h-4 w-4</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">/&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">button</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">div</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">div</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">x</span><span style="color:#C792EA">-</span><span style="color:#82AAFF">show</span><span style="color:#C792EA">=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">dialogOpen</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">class=</span><span style="color:#D9F5DD">"</span><span style="color:#ECC48D">dialog-panel</span><span style="color:#D9F5DD">"</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">&lt;</span><span style="color:#82AAFF">p</span><span style="color:#C792EA">&gt;</span><span style="color:#82AAFF">Extra</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">context</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">for</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">the</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">user</span><span style="color:#7FDBCA">.</span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">p</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">div</span><span style="color:#C792EA">&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#C792EA">&lt;/</span><span style="color:#82AAFF">a</span><span style="color:#C792EA">&gt;</span></div></code></pre></div>
<p>Everything looks correct…
but a button inside a clickable navigation wrapper = accidental page changes.</p>
<p>You click the info button ➜ navigation fires anyway
because the click event bubbles up to <code>&lt;a wire:navigate&gt;</code>.</p>
<h2>After: Full Control Navigation Only When You Decide</h2>
<p>Instead of letting <code>wire:navigate</code> automatically trigger,
we call it manually using <code>Livewire.navigate()</code>.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-diff"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#22863A">+ @script</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#22863A">+     &lt;script&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#22863A">+         window.redirectToTarget = () =&gt; {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#22863A">+             Livewire.navigate(@js(route('target.route', ['param' =&gt; $param-&gt;id])))</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#22863A">+         }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#22863A">+     &lt;/script&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#22863A">+ @endscript</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#B31D28">- &lt;div</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#B31D28">-     x-data="{ dialogOpen: false }"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#22863A">+     x-on:click="redirectToTarget"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#B31D28">-     class="clickable-card"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#B31D28">- &gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#B31D28">-     &lt;h3&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#B31D28">-         Action Title</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#B31D28">-         &lt;button</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#B31D28">-             type="button"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#B31D28">-             x-on:click.stop.prevent="dialogOpen = true"</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#B31D28">-         &gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#B31D28">-             &lt;x-lucide-info /&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#B31D28">-         &lt;/button&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#B31D28">-     &lt;/h3&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#B31D28">-</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#B31D28">-     &lt;p&gt;Short description text&lt;/p&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#B31D28">-</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#B31D28">-     &lt;div x-show="dialogOpen" class="dialog-panel"&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#B31D28">-         &lt;h2&gt;Dialog Title&lt;/h2&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">28</span><span style="color:#B31D28">-         &lt;p&gt;More info goes here.&lt;/p&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">29</span><span style="color:#B31D28">-         &lt;button type="button" x-on:click="dialogOpen = false"&gt;Close&lt;/button&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">30</span><span style="color:#B31D28">-     &lt;/div&gt;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">31</span><span style="color:#B31D28">- &lt;/div&gt;</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-diff"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF"> @script</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">     &lt;script&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">         window.redirectToTarget = () =&gt; {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">             Livewire.navigate(@js(route('target.route', ['param' =&gt; $param-&gt;id])))</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">         }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">     &lt;/script&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF"> @endscript</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#EF535090">-</span><span style="color:#EF535090"> &lt;div</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     x-data="{ dialogOpen: false }"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#C5E478FF">+</span><span style="color:#C5E478FF">     x-on:click="redirectToTarget"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     class="clickable-card"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#EF535090">-</span><span style="color:#EF535090"> &gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     &lt;h3&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         Action Title</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &lt;button</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#EF535090">-</span><span style="color:#EF535090">             type="button"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#EF535090">-</span><span style="color:#EF535090">             x-on:click.stop.prevent="dialogOpen = true"</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#EF535090">-</span><span style="color:#EF535090">             &lt;x-lucide-info /&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &lt;/button&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     &lt;/h3&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#EF535090">-</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     &lt;p&gt;Short description text&lt;/p&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#EF535090">-</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     &lt;div x-show="dialogOpen" class="dialog-panel"&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &lt;h2&gt;Dialog Title&lt;/h2&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">28</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &lt;p&gt;More info goes here.&lt;/p&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">29</span><span style="color:#EF535090">-</span><span style="color:#EF535090">         &lt;button type="button" x-on:click="dialogOpen = false"&gt;Close&lt;/button&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">30</span><span style="color:#EF535090">-</span><span style="color:#EF535090">     &lt;/div&gt;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">31</span><span style="color:#EF535090">-</span><span style="color:#EF535090"> &lt;/div&gt;</span></div></code></pre></div>
<h3>Why This Works</h3>
<ul>
<li>The card itself controls navigation using <code>redirectToTarget()</code></li>
<li>The dialog button stops the click from bubbling up (<code>.stop.prevent</code>)</li>
<li>You decide when <strong>navigation</strong> should fire not the browser</li>
</ul>
<p>No hacks. No overlays.
Just letting Alpine handle UI, and Livewire handle navigation independently.</p>
<h3>Key Lesson</h3>
<p>When combining Alpine interactions inside click-based navigation:</p>
<ul>
<li>Stop clicks meant for UI elements</li>
<li>Trigger navigation programmatically</li>
<li>Keep control where it belongs</li>
</ul>
<p>Sometimes the cleanest solution starts with simply reading the docs.</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Rebase Like a Pro: Laravel Ahmedabad Talk Recap]]></title>
            <link>https://utsavsomaiya.in/articles/rebase-like-a-pro-laravel-ahmedabad-talk-recap</link>
            <guid>https://utsavsomaiya.in/articles/rebase-like-a-pro-laravel-ahmedabad-talk-recap</guid>
            <pubDate>Sun, 29 Jun 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<h2>Introduction</h2>
<p>Git is one of the most powerful tools in a developer’s toolkit — and while we all use it, few of us use it to its full potential. In my talk at the Laravel Ahmedabad meetup, I dived deep into one of Git’s most underrated and misunderstood features: <code>rebase</code>.</p>
<p>In this blog post, I’ll summarize the key points from my talk, share practical tips, and link to the slides for those who missed it.</p>
<h2>Why Learn <code>git rebase</code>?</h2>
<p>Many developers stick to <code>git merge</code> because it’s safer and easier to understand. But learning how to rebase can help you:</p>
<ul>
<li>Keep your commit history clean and linear.</li>
<li>Avoid unnecessary merge commits.</li>
<li>Make code review easier for your team.</li>
<li>Squash and reword commits before pushing to main branches.</li>
</ul>
<h2>Understanding the Basics</h2>
<p><strong>Merge vs Rebase</strong></p>
<ul>
<li><strong>Merge</strong>: Combines two branches, preserving both histories.</li>
<li><strong>Rebase</strong>: Rewrites your commits to apply them <em>on top of</em> another base commit.</li>
</ul>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D"># Typical use</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#032F62">main</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">#</span><span style="color:#637777"> Typical use</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">main</span></div></code></pre></div>
<p>This moves your feature branch commits to be "on top of" the latest main.</p>
<h3>Live Demo Highlights</h3>
<p>Here’s what we walked through in the session:</p>
<ol>
<li><strong>Rebase a Feature Branch</strong></li>
</ol>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">checkout</span><span style="color:#24292E"> </span><span style="color:#032F62">feature-xyz</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">fetch</span><span style="color:#24292E"> </span><span style="color:#032F62">origin</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#032F62">origin/main</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">checkout</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">feature-xyz</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">fetch</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">origin</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">origin/main</span></div></code></pre></div>
<ol start="2">
<li><strong>Squash Commits Before Merging</strong></li>
</ol>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#005CC5">-i</span><span style="color:#24292E"> </span><span style="color:#032F62">HEAD~3</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">-i</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">HEAD~3</span></div></code></pre></div>
<p>Pick, squash, and reword commits interactively.</p>
<ol start="3">
<li><strong>Abort a Rebase</strong></li>
</ol>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#005CC5">--abort</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">--abort</span></div></code></pre></div>
<ol start="4">
<li><strong>Continue Rebase After Conflict Resolution</strong></li>
</ol>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D"># Resolve conflicts</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">add</span><span style="color:#24292E"> </span><span style="color:#005CC5">.</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#005CC5">--continue</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">#</span><span style="color:#637777"> Resolve conflicts</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">add</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">.</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">--continue</span></div></code></pre></div>
<h3>Rebase in Pull Requests</h3>
<p>Here’s a great workflow to keep your PRs clean:</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">checkout</span><span style="color:#24292E"> </span><span style="color:#032F62">feature-abc</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">fetch</span><span style="color:#24292E"> </span><span style="color:#032F62">origin</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">rebase</span><span style="color:#24292E"> </span><span style="color:#032F62">origin/main</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">push</span><span style="color:#24292E"> </span><span style="color:#005CC5">--force-with-lease</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">checkout</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">feature-abc</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">fetch</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">origin</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">rebase</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">origin/main</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">push</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">--force-with-lease</span></div></code></pre></div>
<p>Note: Use <code>--force-with-lease</code> instead of <code>--force</code> to avoid overwriting others’ changes on shared branches.</p>
<h3>When NOT to Rebase</h3>
<blockquote>
<p>Never rebase shared or public branches that others are working on.</p>
</blockquote>
<p>Rebase rewrites history. Do it <em>only</em> on local branches or branches you control.</p>
<h3>Slides from the Talk</h3>
<p>You can view or download the slides here: <a href="https://github.com/utsavsomaiya/laravel-ahmedabad">Rebase Like a Pro: Slide Deck (Livewire app)</a></p>
<h3>Wrap Up</h3>
<p>Rebasing is a superpower once you master it. It’s cleaner, smarter, and can seriously improve your Git hygiene. especially in collaborative Laravel projects.</p>
<p>Have any questions or want to dive deeper into Git workflows? Drop me a message on <a href="https://x.com/SomaiyaUtsav">Twitter</a> or <a href="https://github.com/utsavsomaiya">GitHub</a>!</p>
<h3>Tools Mentioned</h3>
<ul>
<li>Git CLI</li>
<li>GitLens (VS Code Extension)</li>
<li>GitHub / GitLab UI for rebase &amp; squash</li>
</ul>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[Single-use Tests]]></title>
            <link>https://utsavsomaiya.in/articles/single-use-tests</link>
            <guid>https://utsavsomaiya.in/articles/single-use-tests</guid>
            <pubDate>Sun, 04 Aug 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>The tests I write are usually written in Pest, PHPUnit, or Jest. I also usually commit them to a code repository - but not all automated tests should be committed. I wrote what I consider to be an automated test that was a "single-use test". It served its purpose and it will forever be in my heart, but not in my repository.</p>
<p>A tiny script I created allowed me to verify, with certainty, that I had not modified any route definitions after a pretty decent-sized refactor that touched a lot of different parts of the application. I thought it was pretty neat and gave me a lot of confidence to ship the changes, so I thought I would share.</p>
<p>In a project I’m working on there are duplicated middleware added to a lot of routes. At some point, in this projects long life, the way middleware was added to routes was moved from controller constructor middleware to the route file middleware (where they belong 😎).</p>
<p>If you aren’t familiar with these two options for adding middleware to a route, Laravel allows you to add middleware in a routes file...</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#6A737D">// routes/web.php</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Http\Middleware\Authenticate</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Http\Middleware\MonitorUsage</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Route</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#6A737D">// Apply middleware to a group of routes...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#005CC5">Route</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">Authenticate</span><span style="color:#D73A49">::class</span><span style="color:#24292E">)</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">group</span><span style="color:#24292E">(</span><span style="color:#D73A49">function</span><span style="color:#24292E"> () {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    </span><span style="color:#6A737D">// Apply middleware to a single route...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">    </span><span style="color:#005CC5">Route</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">get</span><span style="color:#24292E">(</span><span style="color:#6A737D">/* ... */</span><span style="color:#24292E">)</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">MonitorUsage</span><span style="color:#D73A49">::class</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">});</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#637777">//</span><span style="color:#637777"> routes/web.php</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Http\Middleware\</span><span style="color:#FFCB8B">Authenticate</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Http\Middleware\</span><span style="color:#FFCB8B">MonitorUsage</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Route</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#637777">//</span><span style="color:#637777"> Apply middleware to a group of routes...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#FFCB8B">Route</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">Authenticate</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">)</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">group</span><span style="color:#D6DEEB">(</span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> Apply middleware to a single route...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">Route</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">get</span><span style="color:#D6DEEB">(</span><span style="color:#637777">/*</span><span style="color:#637777"> ... </span><span style="color:#637777">*/</span><span style="color:#D6DEEB">)</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">MonitorUsage</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">});</span></div></code></pre></div>
<p>Laravel also allows you to add middleware to routes via the controller’s constructor. These middleware will apply to all methods on the controller unless otherwise configured.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">namespace</span><span style="color:#24292E"> </span><span style="color:#6F42C1">App\Http\Controllers</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Http\Middleware\Authenticate</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Http\Middleware\MonitorUsage</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D73A49">class</span><span style="color:#24292E"> </span><span style="color:#6F42C1">UserController</span><span style="color:#24292E"> </span><span style="color:#D73A49">extends</span><span style="color:#24292E"> </span><span style="color:#6F42C1">Controller</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">    </span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#005CC5">__construct</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">    {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">        </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">Authenticate</span><span style="color:#D73A49">::class</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">        </span><span style="color:#005CC5">$this</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">MonitorUsage</span><span style="color:#D73A49">::class</span><span style="color:#24292E">, [</span><span style="color:#032F62">'only'</span><span style="color:#24292E"> </span><span style="color:#D73A49">=&gt;</span><span style="color:#24292E"> </span><span style="color:#032F62">'show'</span><span style="color:#24292E">]);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#24292E">    </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">namespace</span><span style="color:#D6DEEB"> App\Http\Controllers;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Http\Middleware\</span><span style="color:#FFCB8B">Authenticate</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Http\Middleware\</span><span style="color:#FFCB8B">MonitorUsage</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">UserController</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">extends</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">Controller</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#C5E478">__construct</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">    {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">Authenticate</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">        </span><span style="color:#7FDBCA">$this-&gt;</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">MonitorUsage</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">, [</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">only</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB"> </span><span style="color:#7FDBCA">=&gt;</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">show</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">]);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#D6DEEB">    </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>As I mentioned, this project had moved from using controller middleware to route file middleware, however the middleware in the controllers had not yet been tidied up and removed.</p>
<p>This wasn’t really a problem.</p>
<p>It wasn’t like these middleware were being run twice. Laravel deduplicates middleware applied to a route, i.e., if we add the same middleware to a route more than once it is only executed once.</p>
<p>We can see this with a quick example. I'll create an empty middleware that dumps a message when it is run.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D73A49">namespace</span><span style="color:#24292E"> </span><span style="color:#6F42C1">App\Http\Middleware</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D73A49">class</span><span style="color:#24292E"> </span><span style="color:#6F42C1">MyMiddleware</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#24292E">    </span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">handle</span><span style="color:#24292E">($request, $next)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">    {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">        </span><span style="color:#6F42C1">dump</span><span style="color:#24292E">(</span><span style="color:#032F62">'Running my middleware.'</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">        </span><span style="color:#D73A49">return</span><span style="color:#24292E"> $next($request);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">    }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#C792EA">namespace</span><span style="color:#D6DEEB"> App\Http\Middleware;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">MyMiddleware</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">handle</span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$request</span><span style="color:#D6DEEB">, </span><span style="color:#BEC5D4">$next</span><span style="color:#D9F5DD">)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">    {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">        </span><span style="color:#82AAFF">dump</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Running my middleware.</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">        </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#BEC5D4">$next</span><span style="color:#D6DEEB">(</span><span style="color:#BEC5D4">$request</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">    }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>I can then create a route and apply the middleware to it twice; once via a wrapping group and once on the actual route itself.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D">// routes/web.php</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">App\Middleware\MyMiddleware</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Illuminate\Support\Facades\Route</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#005CC5">Route</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">MyMiddleware</span><span style="color:#D73A49">::class</span><span style="color:#24292E">)</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">group</span><span style="color:#24292E">(</span><span style="color:#D73A49">function</span><span style="color:#24292E"> () {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">    </span><span style="color:#005CC5">Route</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">get</span><span style="color:#24292E">(</span><span style="color:#032F62">'/'</span><span style="color:#24292E">, </span><span style="color:#D73A49">fn</span><span style="color:#24292E"> () =&gt; </span><span style="color:#032F62">'Welcome!'</span><span style="color:#24292E">)</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">middleware</span><span style="color:#24292E">(</span><span style="color:#005CC5">MyMiddleware</span><span style="color:#D73A49">::class</span><span style="color:#24292E">);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#24292E">});</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">//</span><span style="color:#637777"> routes/web.php</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> App\Middleware\</span><span style="color:#FFCB8B">MyMiddleware</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Illuminate\Support\Facades\</span><span style="color:#FFCB8B">Route</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#FFCB8B">Route</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">MyMiddleware</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">)</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">group</span><span style="color:#D6DEEB">(</span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">    </span><span style="color:#FFCB8B">Route</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">get</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">/</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">, </span><span style="color:#C792EA">fn</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">()</span><span style="color:#D6DEEB"> =&gt; </span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">Welcome!</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">)</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">middleware</span><span style="color:#D6DEEB">(</span><span style="color:#FFCB8B">MyMiddleware</span><span style="color:#7FDBCA">::</span><span style="color:#C792EA">class</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">8</span><span style="color:#D6DEEB">});</span></div></code></pre></div>
<p>When we access this page we see the following output rendered in the browser. You will notice that the dump is only seen once, indicating that Laravel has removed the duplicate middleware from the stack.</p>
<img alt="" loading="lazy" width="4064" height="2624" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmiddleware-running-once.37ec79bb.png&amp;w=3840&amp;q=75 1x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fmiddleware-running-once.37ec79bb.png&amp;w=3840&amp;q=75">
<p>So cleaning this up was about aesthetics and consistency - or so I thought!</p>
<p>I decided to finally dig in and refactor it away. I came up with a plan and started doing a, rather manual, systematic route-by-route check.</p>
<ol>
<li>Look at the route.</li>
<li>Work out the applied middleware in the routes file.</li>
<li>Move to the controller constructor.</li>
<li>Verify the middleware applied matched or was at least a subset of the route file middleware.</li>
<li>Remove the middleware from the constructor.</li>
<li>Make any required adjustments in the route file.</li>
</ol>
<p>I did this for about 2 minutes before it dawned on me that whoever reviews this is gonna have a bad time. We would either YOLO it into production and hope the testsuite caught any issues or some poor soul would have to do all this manual checking again while reviewing. Not a fun time.</p>
<p>It wasn’t worth the time / improvement trade off.</p>
<p>I stopped coding; I moved away from the keyboard; I thought…</p>
<p>Do I scrap the changes? It’s not hurting anyone…but it did hurt me. Won’t somebody think of the children!</p>
<p>Then I realised I could potentially automate the review process and MAKE THE ROBOTS DO IT 🤖</p>
<p>Laravel ships with an artisan command that displays all routes defined within the application. There are a few flags on the command to change the commands output.</p>
<p>The bare command, <code>php artisan route:list</code>, will show you the routes.</p>
<img alt="" loading="lazy" width="3778" height="1550" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fbreeze-route-list.66b86f57.png&amp;w=3840&amp;q=75 1x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fbreeze-route-list.66b86f57.png&amp;w=3840&amp;q=75">
<p>But this doesn’t show the route middleware. Using the verbose flag, <code>php artisan route:list -v</code>, will show middleware for each route.</p>
<img alt="" loading="lazy" width="3818" height="1702" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fbreeze-route-list-verbose.4805b2f5.png&amp;w=3840&amp;q=75 1x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fbreeze-route-list-verbose.4805b2f5.png&amp;w=3840&amp;q=75">
<p>Great! We are getting somewhere useful! I then remembered that a <code>--json</code> flag was available on the command to output a JSON representation of the routes and their middleware instead of the visual representation we see in the terminal.</p>
<p>With the combination of all of this I could get all the routes and their respective middleware output before I made the change and then compare the file to the routes after I made the change.</p>
<p>So no more route-by-route review; I went straight for the jugular and stripped out all the middleware from all the controllers in a matter of minutes.</p>
<p>I committed my changes to my <code>working</code> branch.</p>
<p>I crafted the following helper script.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">checkout</span><span style="color:#24292E"> </span><span style="color:#032F62">main</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#6F42C1">php</span><span style="color:#24292E"> </span><span style="color:#032F62">artisan</span><span style="color:#24292E"> </span><span style="color:#032F62">route:list</span><span style="color:#24292E"> </span><span style="color:#005CC5">--json</span><span style="color:#24292E"> </span><span style="color:#005CC5">-v</span><span style="color:#24292E"> </span><span style="color:#D73A49">|</span><span style="color:#24292E"> </span><span style="color:#6F42C1">jq</span><span style="color:#24292E"> </span><span style="color:#D73A49">&gt;</span><span style="color:#24292E"> </span><span style="color:#032F62">before.json</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#6F42C1">git</span><span style="color:#24292E"> </span><span style="color:#032F62">checkout</span><span style="color:#24292E"> </span><span style="color:#032F62">working</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#6F42C1">php</span><span style="color:#24292E"> </span><span style="color:#032F62">artisan</span><span style="color:#24292E"> </span><span style="color:#032F62">route:list</span><span style="color:#24292E"> </span><span style="color:#005CC5">--json</span><span style="color:#24292E"> </span><span style="color:#005CC5">-v</span><span style="color:#24292E"> </span><span style="color:#D73A49">|</span><span style="color:#24292E"> </span><span style="color:#6F42C1">jq</span><span style="color:#24292E"> </span><span style="color:#D73A49">&gt;</span><span style="color:#24292E"> </span><span style="color:#032F62">after.json</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">checkout</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">main</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D6DEEB">php </span><span style="color:#ECC48D">artisan</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">route:list</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">--json</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">-v</span><span style="color:#D6DEEB"> </span><span style="color:#7FDBCA">|</span><span style="color:#D6DEEB"> jq </span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">before.json</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">git </span><span style="color:#ECC48D">checkout</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">working</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">php </span><span style="color:#ECC48D">artisan</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">route:list</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">--json</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">-v</span><span style="color:#D6DEEB"> </span><span style="color:#7FDBCA">|</span><span style="color:#D6DEEB"> jq </span><span style="color:#7FDBCA">&gt;</span><span style="color:#D6DEEB"> </span><span style="color:#ECC48D">after.json</span></div></code></pre></div>
<p>The content of the before.json and after.json files now looks something like the following, which has been truncated for brevity...</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-json"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#24292E">[</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#24292E">  {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#24292E">    </span><span style="color:#005CC5">"domain"</span><span style="color:#24292E">: </span><span style="color:#005CC5">null</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#24292E">    </span><span style="color:#005CC5">"method"</span><span style="color:#24292E">: </span><span style="color:#032F62">"GET|HEAD"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#24292E">    </span><span style="color:#005CC5">"uri"</span><span style="color:#24292E">: </span><span style="color:#032F62">"/"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#24292E">    </span><span style="color:#005CC5">"name"</span><span style="color:#24292E">: </span><span style="color:#005CC5">null</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#24292E">    </span><span style="color:#005CC5">"action"</span><span style="color:#24292E">: </span><span style="color:#032F62">"Closure"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#24292E">    </span><span style="color:#005CC5">"middleware"</span><span style="color:#24292E">: [</span><span style="color:#032F62">"web"</span><span style="color:#24292E">]</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#24292E">  },</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#24292E">  {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#24292E">    </span><span style="color:#005CC5">"domain"</span><span style="color:#24292E">: </span><span style="color:#005CC5">null</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#24292E">    </span><span style="color:#005CC5">"method"</span><span style="color:#24292E">: </span><span style="color:#032F62">"GET|HEAD"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#24292E">    </span><span style="color:#005CC5">"uri"</span><span style="color:#24292E">: </span><span style="color:#032F62">"api/user"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#24292E">    </span><span style="color:#005CC5">"name"</span><span style="color:#24292E">: </span><span style="color:#005CC5">null</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#24292E">    </span><span style="color:#005CC5">"action"</span><span style="color:#24292E">: </span><span style="color:#032F62">"Closure"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#24292E">    </span><span style="color:#005CC5">"middleware"</span><span style="color:#24292E">: [</span><span style="color:#032F62">"api"</span><span style="color:#24292E">, </span><span style="color:#032F62">"App</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Http</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Middleware</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Authenticate:sanctum"</span><span style="color:#24292E">]</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#24292E">  },</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#24292E">  {</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#24292E">    </span><span style="color:#005CC5">"domain"</span><span style="color:#24292E">: </span><span style="color:#005CC5">null</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#24292E">    </span><span style="color:#005CC5">"method"</span><span style="color:#24292E">: </span><span style="color:#032F62">"GET|HEAD"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#24292E">    </span><span style="color:#005CC5">"uri"</span><span style="color:#24292E">: </span><span style="color:#032F62">"confirm-password"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#24292E">    </span><span style="color:#005CC5">"name"</span><span style="color:#24292E">: </span><span style="color:#032F62">"password.confirm"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#24292E">    </span><span style="color:#005CC5">"action"</span><span style="color:#24292E">: </span><span style="color:#032F62">"App</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Http</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Controllers</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Auth</span><span style="color:#005CC5">\\</span><span style="color:#032F62">ConfirmablePasswordController@show"</span><span style="color:#24292E">,</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#24292E">    </span><span style="color:#005CC5">"middleware"</span><span style="color:#24292E">: [</span><span style="color:#032F62">"web"</span><span style="color:#24292E">, </span><span style="color:#032F62">"App</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Http</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Middleware</span><span style="color:#005CC5">\\</span><span style="color:#032F62">Authenticate"</span><span style="color:#24292E">]</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#24292E">  }</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#24292E">  </span><span style="color:#6A737D">// ...</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#24292E">]</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-json"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 1</span><span style="color:#D6DEEB">[</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 2</span><span style="color:#D6DEEB">  {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 3</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"domain"</span><span style="color:#D6DEEB">: </span><span style="color:#FF5874">null</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 4</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"method"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">GET|HEAD</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 5</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"uri"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">/</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 6</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"name"</span><span style="color:#D6DEEB">: </span><span style="color:#FF5874">null</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 7</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"action"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">Closure</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 8</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"middleware"</span><span style="color:#D6DEEB">: [</span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">web</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">]</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number"> 9</span><span style="color:#D6DEEB">  },</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">10</span><span style="color:#D6DEEB">  {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">11</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"domain"</span><span style="color:#D6DEEB">: </span><span style="color:#FF5874">null</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">12</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"method"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">GET|HEAD</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">13</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"uri"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">api/user</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">14</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"name"</span><span style="color:#D6DEEB">: </span><span style="color:#FF5874">null</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">15</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"action"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">Closure</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">16</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"middleware"</span><span style="color:#D6DEEB">: [</span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">api</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">App</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Http</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Middleware</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Authenticate:sanctum</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">]</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">17</span><span style="color:#D6DEEB">  },</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">18</span><span style="color:#D6DEEB">  {</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">19</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"domain"</span><span style="color:#D6DEEB">: </span><span style="color:#FF5874">null</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">20</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"method"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">GET|HEAD</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">21</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"uri"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">confirm-password</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">22</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"name"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">password.confirm</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">23</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"action"</span><span style="color:#D6DEEB">: </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">App</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Http</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Controllers</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Auth</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">ConfirmablePasswordController@show</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">,</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">24</span><span style="color:#D6DEEB">    </span><span style="color:#7FDBCA">"middleware"</span><span style="color:#D6DEEB">: [</span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">web</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">, </span><span style="color:#D9F5DD">"</span><span style="color:#C789D6">App</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Http</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Middleware</span><span style="color:#F78C6C">\\</span><span style="color:#C789D6">Authenticate</span><span style="color:#D9F5DD">"</span><span style="color:#D6DEEB">]</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">25</span><span style="color:#D6DEEB">  }</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">26</span><span style="color:#D6DEEB">  </span><span style="color:#637777">//</span><span style="color:#637777"> ...</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">27</span><span style="color:#D6DEEB">]</span></div></code></pre></div>
<p>The only thing needed now was to compare the two files and see what the damage is. Of course I don't want this to be a manual process either! This step is why I wanted the JSON formatted nicely. If it was all a single line it would be impossible to see the difference. With formatted JSON I can use some tooling to see the exact differences before and after the refactor.</p>
<p>My tool of choice here is the diffing tool built into Kitty, the terminal I use, but you could use any diffing tool you have access to.</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-bash"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6F42C1">diff</span><span style="color:#24292E"> </span><span style="color:#032F62">&lt;(</span><span style="color:#6F42C1">jq</span><span style="color:#032F62"> </span><span style="color:#005CC5">--sort-keys</span><span style="color:#032F62"> </span><span style="color:#005CC5">.</span><span style="color:#032F62"> before.json)</span><span style="color:#24292E"> </span><span style="color:#032F62">&lt;(</span><span style="color:#6F42C1">jq</span><span style="color:#032F62"> </span><span style="color:#005CC5">--sort-keys</span><span style="color:#032F62"> </span><span style="color:#005CC5">.</span><span style="color:#032F62"> after.json)</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-bash"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D6DEEB">diff </span><span style="color:#D9F5DD">&lt;(</span><span style="color:#ECC48D">jq </span><span style="color:#82AAFF">--sort-keys</span><span style="color:#ECC48D"> </span><span style="color:#C5E478">.</span><span style="color:#ECC48D"> before.json</span><span style="color:#D9F5DD">)</span><span style="color:#D6DEEB"> </span><span style="color:#D9F5DD">&lt;(</span><span style="color:#ECC48D">jq </span><span style="color:#82AAFF">--sort-keys</span><span style="color:#ECC48D"> </span><span style="color:#C5E478">.</span><span style="color:#ECC48D"> after.json</span><span style="color:#D9F5DD">)</span></div></code></pre></div>
<p>The result was something that look liked the following...</p>
<img alt="" loading="lazy" width="2812" height="1276" decoding="async" data-nimg="1" style="color:transparent" srcset="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Froute-diff.ff77d4aa.png&amp;w=3840&amp;q=75 1x" src="/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Froute-diff.ff77d4aa.png&amp;w=3840&amp;q=75">
<p>This gave me a way to visualise, with precision, the differences between each route's middleware before and after the change and detect inconsistecies.</p>
<p>I found this super valuable.</p>
<p>I ended up finding a few differences that were inconsistencies between the contructor and route file middleware - so it turns out it wasn't just aesthetics and consistency but actually help identify some places where our constructor middleware was lying to us.</p>
<p>So a PR with <strong>548</strong> deletions and <strong>359</strong> additions across <strong>111</strong> files was easily merge without manual testing.</p>
<p>Why do you care? Because now you can migrate your middleware to the routes file and also completely refactor your routes file to remove the use of <code>Route::prefix</code> and have a flat routes file, the way it should be, without worrying about breaking everything 😎</p>
<p>But hopefully it also gives you some ideas of how you could create single-use tests for your own PRs.</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
        <item>
            <title><![CDATA[A Week So Busy Even My Laptop Asked for a Day Off!]]></title>
            <link>https://utsavsomaiya.in/articles/week-so-busy-even-my-laptop-asked-for-a-day-off</link>
            <guid>https://utsavsomaiya.in/articles/week-so-busy-even-my-laptop-asked-for-a-day-off</guid>
            <pubDate>Sun, 22 Sep 2024 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<p>Let me tell you, this week has been a rollercoaster ride. 🎢</p>
<h2>Monday: The "12-Hour Shift Marathon" 🕛</h2>
<p>Monday kicked off strong. By strong, I mean 12 hours of non-stop work. I think my chair now has an imprint of my soul. 😅 Every time I thought I was done, something else popped up! But hey, at least I managed to tackle some Laravel domain work. Writing domain logic? Easy peasy! 💻</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#6A737D">// Laravel domain stuff — smooth as butter!</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">handleDomainStuff</span><span style="color:#24292E">($request)</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#24292E">    </span><span style="color:#D73A49">return</span><span style="color:#24292E"> </span><span style="color:#005CC5">DomainLogic</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">process</span><span style="color:#24292E">($request);</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#637777">//</span><span style="color:#637777"> Laravel domain stuff — smooth as butter!</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">handleDomainStuff</span><span style="color:#D9F5DD">(</span><span style="color:#BEC5D4">$request</span><span style="color:#D9F5DD">)</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">DomainLogic</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">process</span><span style="color:#D6DEEB">(</span><span style="color:#BEC5D4">$request</span><span style="color:#D6DEEB">);</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>Then came the real challenge...</p>
<h2>Tuesday: Google Authentication, but with a Twist 🧩</h2>
<p>You know how Laravel Socialite makes Google authentication sound like a breeze? Well, it is... unless you're dealing with multiple domains and a central point of failure. Trying to manage Socialite redirects across different domains was like trying to teach a cat to play fetch. 🐱</p>
<div class="torchlight-theme-wrapper"><pre class="torchlight torchlight-theme-light" style="background-color:#fff;--theme-selection-background:#e2e5e9"><code class="language-php"><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#D73A49">use</span><span style="color:#24292E"> </span><span style="color:#005CC5">Laravel\Socialite\Facades\Socialite</span><span style="color:#24292E">;</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#6A737D">// Seems easy, but not with multi-domain redirects!</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#D73A49">public</span><span style="color:#24292E"> </span><span style="color:#D73A49">function</span><span style="color:#24292E"> </span><span style="color:#6F42C1">redirectToGoogle</span><span style="color:#24292E">()</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#24292E">{</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#24292E">    </span><span style="color:#D73A49">return</span><span style="color:#24292E"> </span><span style="color:#005CC5">Socialite</span><span style="color:#D73A49">::</span><span style="color:#6F42C1">driver</span><span style="color:#24292E">(</span><span style="color:#032F62">'google'</span><span style="color:#24292E">)</span><span style="color:#D73A49">-&gt;</span><span style="color:#6F42C1">redirect</span><span style="color:#24292E">();</span></div><div class="line"><span style="color:#1b1f234d;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#24292E">}</span></div></code></pre><pre class="torchlight torchlight-theme-dark" style="background-color:#011627;--theme-selection-background:#4373c2"><code class="language-php"><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">1</span><span style="color:#C792EA">use</span><span style="color:#D6DEEB"> Laravel\Socialite\Facades\</span><span style="color:#FFCB8B">Socialite</span><span style="color:#D6DEEB">;</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">2</span>&nbsp;</div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">3</span><span style="color:#637777">//</span><span style="color:#637777"> Seems easy, but not with multi-domain redirects!</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">4</span><span style="color:#C792EA">public</span><span style="color:#D6DEEB"> </span><span style="color:#C792EA">function</span><span style="color:#D6DEEB"> </span><span style="color:#82AAFF">redirectToGoogle</span><span style="color:#D9F5DD">()</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">5</span><span style="color:#D6DEEB">{</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">6</span><span style="color:#D6DEEB">    </span><span style="color:#C792EA">return</span><span style="color:#D6DEEB"> </span><span style="color:#FFCB8B">Socialite</span><span style="color:#7FDBCA">::</span><span style="color:#82AAFF">driver</span><span style="color:#D6DEEB">(</span><span style="color:#D9F5DD">'</span><span style="color:#ECC48D">google</span><span style="color:#D9F5DD">'</span><span style="color:#D6DEEB">)</span><span style="color:#7FDBCA">-&gt;</span><span style="color:#82AAFF">redirect</span><span style="color:#D6DEEB">();</span></div><div class="line"><span style="color:#4b6479;text-align:right;-webkit-user-select:none;user-select:none" class="line-number">7</span><span style="color:#D6DEEB">}</span></div></code></pre></div>
<p>Pro tip: Remember to triple-check your redirect URIs, or you'll be pulling your hair out wondering why Google thinks you're an imposter.</p>
<h2>Interns, Interns Everywhere! 😵</h2>
<p>And don’t get me started on managing interns while juggling all this. I spent more time explaining the difference between <code>git fetch</code> and <code>git pull</code> than I did coding. At this rate, I’ll be adding Intern Wrangler to my LinkedIn profile.</p>
<p>Wednesday to Friday was basically more of the same, but with slightly fewer hours and more coffee.</p>
<h2>Friday: Wrapping Up with a Smile 😎</h2>
<p>By Friday, I was down to a solid 8 hours, but still, no day off in sight! My weekend plan? Sleep. 💤</p>
<p>Conclusion? Multi-domain authentication isn’t for the faint-hearted, but hey, if I can survive this week, I can survive anything! 🎉</p>
<hr>
<p>Hope you enjoyed the chaos! Time to treat myself to a well-deserved break... or at least a second cup of coffee. ☕</p>]]></content:encoded>
            <author>hello@utsavsomaiya.in (Utsav Somaiya)</author>
        </item>
    </channel>
</rss>