<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Adebowale Bello</title>
    <description>The latest articles on Forem by Adebowale Bello (@devbalop).</description>
    <link>https://forem.com/devbalop</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1183471%2F99583e02-742a-4852-a826-20e4aba9ff19.jpeg</url>
      <title>Forem: Adebowale Bello</title>
      <link>https://forem.com/devbalop</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/devbalop"/>
    <language>en</language>
    <item>
      <title>Building APIs with a Zero Trust Policy: Protecting Your Data Like Your Peace</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Fri, 31 Oct 2025 14:20:59 +0000</pubDate>
      <link>https://forem.com/devbalop/building-apis-with-a-zero-trust-policy-protecting-your-data-like-your-peace-2ifg</link>
      <guid>https://forem.com/devbalop/building-apis-with-a-zero-trust-policy-protecting-your-data-like-your-peace-2ifg</guid>
      <description>&lt;p&gt;If you have ever been hurt by someone you trusted completely, you already understand the essence of &lt;strong&gt;Zero Trust Policy&lt;/strong&gt;, you just didn’t know it had a name or is relatable in Api Architecting.&lt;/p&gt;

&lt;p&gt;In life, we learn (sometimes the hard way) that trust is something you verify, not something you give blindly. You don’t expect everyone to always do right by you. People have different upbringing, grew up in different environments, have had different experiences and most naturally do things that make life convenient &lt;em&gt;for themselves&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, what do you do?&lt;br&gt;
You start setting boundaries. You keep your guard up. You make sure no one can hurt you, not because you don’t trust people, but because you trust that &lt;em&gt;anyone is capable of breaking your trust if it benefits them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is exactly how I approach &lt;strong&gt;API development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When I build APIs, I build them with a &lt;strong&gt;Zero Trust policy&lt;/strong&gt; not because I am paranoid, but because I have seen what happens when assumptions go unchecked. This mindset has saved me countless hours debugging mysterious data inconsistencies and unexpected system failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What Is Zero Trust, Really?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In traditional systems, developers often assume that once a request comes from within the network, it’s safe.&lt;br&gt;
“Oh, it is from another internal service, let it pass.”&lt;br&gt;
That is the same as saying, &lt;em&gt;“They are my friend, they would never do me wrong.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And then you wake up one morning to realize that someone inside the circle left the door wide open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero Trust&lt;/strong&gt; flips that assumption on its head. It means:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Never trust. Always verify.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every request, whether it is coming from your frontend app, a third-party integration, or another internal microservice must prove itself worthy of access. Every bit of data must be verified before it is accepted. Every operation must respect strict permissions.&lt;/p&gt;

&lt;p&gt;In short, Zero Trust is about &lt;strong&gt;respecting boundaries&lt;/strong&gt;, both in life and in code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Zero Trust Shapes API Development&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you apply Zero Trust principles to API design, you’re saying:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don’t care who you are, show your credentials.&lt;/li&gt;
&lt;li&gt;I don’t care where you are calling from, prove your permission.&lt;/li&gt;
&lt;li&gt;I don’t care if it “worked yesterday”, validate your data again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not cynicism. It’s discipline.&lt;br&gt;
And this discipline leads to &lt;strong&gt;more secure and more consistent systems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s break it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Authentication at Every Door&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Think of authentication as checking who is knocking.&lt;br&gt;
You would not let someone into your house just because they say, “I live next door.” You would still look through the peephole, right?&lt;/p&gt;

&lt;p&gt;APIs should do the same.&lt;br&gt;
Every request, even internal ones must carry valid credentials.&lt;br&gt;
That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using &lt;strong&gt;OAuth2, JWTs, or signed API keys&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Verifying tokens for &lt;strong&gt;each&lt;/strong&gt; call, not just trusting the previous one.&lt;/li&gt;
&lt;li&gt;Avoiding network-based trust like IP whitelisting. It is the digital version of leaving your spare key under the mat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a Zero Trust world, &lt;strong&gt;no endpoint is “safe” by default&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Authorization: Just Because You are In Does not Mean You Can Do Everything&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine giving someone your house key to watch a football game, and then coming home to find they rearranged your furniture.&lt;br&gt;
They were authorized to enter, but not to &lt;em&gt;redesign your life.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is why &lt;strong&gt;authorization&lt;/strong&gt; matters.&lt;/p&gt;

&lt;p&gt;After verifying &lt;em&gt;who&lt;/em&gt; someone is, your API must check &lt;em&gt;what they are allowed to do.&lt;/em&gt;&lt;br&gt;
Every endpoint should enforce permissions tightly and deliberately.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;viewer&lt;/code&gt; role shouldn’t be able to update records.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;report:read&lt;/code&gt; scope shouldn’t allow report deletion.&lt;/li&gt;
&lt;li&gt;Internal services should use role-based access just like users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what Zero Trust looks like in practice: &lt;strong&gt;granular control&lt;/strong&gt;. Nobody gets blanket permission.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Input Validation: Don't Let Dirty Data in Your House&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the easiest ways to lose control of your system is to trust incoming data.&lt;br&gt;
Zero Trust means every input, even from “trusted” services is a suspect until proven clean.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validating payloads against a schema or DTO.&lt;/li&gt;
&lt;li&gt;Rejecting malformed requests instead of “fixing” them silently.&lt;/li&gt;
&lt;li&gt;Sanitizing strings to prevent injections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In real life, this is like checking every gift before opening it. This is not because you expect danger, but because you have seen what happens when you don’t.&lt;/p&gt;

&lt;p&gt;And here is the benefit: by treating every input with suspicion, you protect your &lt;strong&gt;data consistency&lt;/strong&gt;. Invalid data never enters your database, which means fewer weird bugs and cleaner analytics downstream.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Data Verification Between Services&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Microservices are like roommates sharing the same fridge.&lt;br&gt;
You can not assume everyone will label their food properly or clean up after themselves.&lt;br&gt;
So, you start setting rules: “Label everything, or it gets thrown out.”&lt;/p&gt;

&lt;p&gt;In a distributed system, the same logic applies.&lt;br&gt;
Just because Service A says “this record is valid” doesn’t mean Service B should skip its own checks.&lt;br&gt;
Every boundary between APIs, between queues, between databases must have its own &lt;strong&gt;validation gate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Zero Trust across services prevents small inconsistencies from spreading into large-scale data corruption.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Observability: Trust, but Verify and Log Everything&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A Zero Trust system should always be able to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who called this endpoint?&lt;/li&gt;
&lt;li&gt;What data did they send?&lt;/li&gt;
&lt;li&gt;Was it valid?&lt;/li&gt;
&lt;li&gt;What changed as a result?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comprehensive &lt;strong&gt;logging and tracing&lt;/strong&gt; are the backbone of verification. They make your APIs auditable and help track data lineage which is a key part of maintaining consistency over time.&lt;/p&gt;

&lt;p&gt;When something goes wrong (and it will), you won’t have to guess. You’ll have evidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Zero Trust Leads to Data Consistency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you stop making assumptions, your data stops lying to you.&lt;/p&gt;

&lt;p&gt;Here is how Zero Trust drives consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every validation step ensures data correctness.&lt;/li&gt;
&lt;li&gt;Every authorization check ensures intentionality.&lt;/li&gt;
&lt;li&gt;Every log ensures traceability.&lt;/li&gt;
&lt;li&gt;Every boundary enforces accountability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of building brittle systems that rely on “good behaviour,” you build resilient ones that rely on &lt;strong&gt;good rules&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Zero Trust turns your API ecosystem into a well-guarded house, every door locked, every guest accounted for, and every rule enforced.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thoughts: Trust Rules, Not People&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Building APIs with Zero Trust isn’t about being skeptical, it’s about being smart.&lt;br&gt;
It’s the digital version of emotional boundaries: you don’t assume everyone will do the right thing, you make sure they &lt;em&gt;can’t do the wrong thing unnoticed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When every request is verified, every piece of data validated, and every service held accountable, your system becomes both secure and consistent not by luck, but by design.&lt;/p&gt;

&lt;p&gt;And just like in life, when you protect your peace (or your data) through boundaries, you create an environment that is safer, cleaner, and much easier to live and build in.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>security</category>
    </item>
    <item>
      <title>API Access Control in Action: How I Protected My Team’s APIs from Unauthorized Access</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Tue, 16 Sep 2025 02:43:23 +0000</pubDate>
      <link>https://forem.com/devbalop/api-access-control-in-action-how-i-protected-my-teams-apis-from-unauthorized-access-3o01</link>
      <guid>https://forem.com/devbalop/api-access-control-in-action-how-i-protected-my-teams-apis-from-unauthorized-access-3o01</guid>
      <description>&lt;p&gt;In every software project, there are moments where technical expertise is tested not by code complexity, but by human behaviour. On one of my projects, I faced such a moment when a mobile developer on the team went rogue.&lt;/p&gt;

&lt;p&gt;He became unprofessional, violated trust, and refused to respect NDA terms or return the mobile app code that consumed our APIs. The bigger risk was not the code itself, but the fact that he still had an active client wired directly to our backend APIs. If left unchecked, he could continue consuming and potentially misusing our services indefinitely.&lt;/p&gt;

&lt;p&gt;The team needed a solution, and I was asked to take control of the situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Approach
&lt;/h2&gt;

&lt;p&gt;I decided the best way to handle this was &lt;strong&gt;professionally and technically&lt;/strong&gt;, without confrontation. Instead of chasing the developer, I focused on what I could control: &lt;strong&gt;the APIs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The answer lay in implementing &lt;strong&gt;API Access Control&lt;/strong&gt;, combining two mechanisms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A kill switch&lt;/strong&gt; to disable APIs entirely when needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key-based restrictions&lt;/strong&gt; to ensure only authorized clients could access endpoints.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This gave us immediate leverage and allowed us to continue operating without disruption.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Middleware I Wrote
&lt;/h2&gt;

&lt;p&gt;I created a custom Laravel middleware called &lt;code&gt;DisableApiAccess&lt;/code&gt; that enforced these controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. API Kill Switch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$apiAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;filter_var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'API_ACCESS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;FILTER_VALIDATE_BOOLEAN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$apiAccess&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expectsJson&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api/*'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apiresponser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'API access is temporarily disabled.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Service unavailable.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By flipping a single environment variable (&lt;code&gt;API_ACCESS=false&lt;/code&gt;), I could immediately &lt;strong&gt;shut down all API endpoints&lt;/strong&gt; with an HTTP 503 response. This was my emergency brake, no redeployments, no code edits, just an instant cut-off.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. API Key Enforcement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$expectedKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'API_ACCESS_KEY'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$expectedKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expectsJson&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api/*'&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$provided&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X-API-ACCESS-KEY'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Api-Access-Key'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$provided&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apiresponser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'API access key missing.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;hash_equals&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$expectedKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$provided&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;apiresponser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Invalid API access key.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With an &lt;code&gt;API_ACCESS_KEY&lt;/code&gt; configured, every request now required the correct header (&lt;code&gt;X-API-ACCESS-KEY&lt;/code&gt; or &lt;code&gt;Api-Access-Key&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing header → &lt;strong&gt;401 Unauthorized&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Wrong key → &lt;strong&gt;401 Unauthorized&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Correct key → proceed as normal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also used &lt;code&gt;hash_equals()&lt;/code&gt; for constant-time comparison to prevent timing attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Normal Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the request passed both checks, it continued safely to the controller. If not, it was blocked at the middleware layer, long before touching business logic or the database.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow Diagram
&lt;/h2&gt;

&lt;p&gt;Here is how the request flow looked after I put the middleware in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ┌─────────────────────────┐
 │  Incoming API Request   │
 └─────────────┬───────────┘
               │
               ▼
     ┌──────────────────┐
     │  Middleware:     │
     │ DisableApiAccess │
     └─────────┬────────┘
               │
     Is API_ACCESS=false?
          │        │
        YES        NO
        │          │
        ▼          ▼
 ┌────────────┐   Check if API_ACCESS_KEY is set
 │ Return 503 │          │
 │ Service     │          │
 │ Unavailable │          ▼
 └────────────┘   Key Required?
                      │
                ┌─────┴─────┐
                │           │
             NO │           │ YES
                │           ▼
                ▼     Validate Header
         Allow Request   │
                         ▼
             ┌─────────────────────┐
             │ Valid Key?          │
             └─────┬───────────────┘
                   │
            ┌──────┴───────┐
            │              │
          YES              NO
            │              │
            ▼              ▼
  ┌────────────────┐   ┌──────────────┐
  │ Proceed to     │   │ Return 401   │
  │ Controller     │   │ Unauthorized │
  └────────────────┘   └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;By putting this in place, I was able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Revoke access immediately&lt;/strong&gt; for the rogue developer, without touching his app or escalating the conflict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure the backend APIs&lt;/strong&gt; so that only trusted clients with the right key could access them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give the team confidence&lt;/strong&gt; that we were still in control of the system, regardless of what happened with the mobile code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The developer still had his app, but without valid API access, it was useless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Was Important
&lt;/h2&gt;

&lt;p&gt;What I implemented aligned with industry best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;strong&gt;Zero Trust Principles&lt;/strong&gt; – Never assume a client is trustworthy just because it was once authorized.&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Operational Control&lt;/strong&gt; – The kill switch provided instant response capability in case of emergencies.&lt;/li&gt;
&lt;li&gt;🛡️ &lt;strong&gt;Defense in Depth&lt;/strong&gt; – Unauthorized requests were stopped at the middleware layer, before causing harm.&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Professional Conflict Resolution&lt;/strong&gt; – I avoided unnecessary escalation, kept the team’s integrity intact, and let the system enforce the rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;APIs must be treated as critical assets.&lt;/strong&gt; Anyone with client access can become a risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revocation paths are non-negotiable.&lt;/strong&gt; It is not enough to grant access; you must always have a way to revoke it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leadership often means quiet technical decisions.&lt;/strong&gt; Instead of drama, I solved the issue with clean code and precise safeguards.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;In the end, I did not just block a rogue developer, I safeguarded the project and gave my team a way forward.&lt;/p&gt;

&lt;p&gt;This experience reinforced something I now apply in every system I design: &lt;strong&gt;control must be baked into the architecture, not assumed through trust.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When asked to protect the team and the project, I did it not with confrontation, but with a simple, robust solution: &lt;strong&gt;API Access Control.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But this is just one approach. If you were in my shoes, what other strategies would you have considered to keep the APIs safe without escalating the conflict? I would love to hear your thoughts. Please share them in the comments so we can learn from each other’s perspectives.&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>From Intern to Technical Lead: Navigating the Steep Climb</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Tue, 11 Mar 2025 11:06:14 +0000</pubDate>
      <link>https://forem.com/devbalop/from-intern-to-technical-lead-navigating-the-steep-climb-527e</link>
      <guid>https://forem.com/devbalop/from-intern-to-technical-lead-navigating-the-steep-climb-527e</guid>
      <description>&lt;p&gt;The journey from an intern to a technical team lead is anything but linear. It is a steep, demanding climb filled with sharp learning curves, moments of doubt, and the relentless pulse of professional expectations. My transition, which began with an eagerness to learn, evolved into a role where I became the go-to person for answers, the face of accountability, and the bridge between stakeholders and cross-functional teams. However, this journey would not have been possible without the incredible support of my team and the growth-driven culture of my company.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Steep Learning Curve
&lt;/h3&gt;

&lt;p&gt;As an intern, my primary focus was absorbing knowledge, understanding codebases, debugging issues, and taking on small tasks to prove my competence. Every line of code was an opportunity to learn, and every mistake was a stepping stone toward growth. But the learning curve only grew steeper as I took on more responsibility. It was no longer just about writing functional code; it was about writing scalable, maintainable, and efficient solutions that aligned with business goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pulse: Keeping Up with the Pace
&lt;/h3&gt;

&lt;p&gt;The transition to leadership wasn’t simply about mastering technical concepts. It required understanding the pulse of the team, the product, and the company. Deadlines became more than just dates; they were commitments I had to ensure were met. Every decision carried weight, impacting performance, user experience, and business outcomes. The pace was relentless, but adapting quickly became second nature.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Strength of a Great Team
&lt;/h3&gt;

&lt;p&gt;No leader thrives alone. I have been fortunate to work alongside a talented, dedicated team that makes the challenges of leadership easier to navigate. Their collaboration, expertise, and ability to rise to challenges have been instrumental in our collective success. From brainstorming solutions to supporting each other in high-pressure situations, my teammates have been a pillar of strength in this journey.&lt;/p&gt;

&lt;p&gt;And of course, one of the most amusing parts of this journey has been seeing distant colleagues stumble upon my profile on Teams. The moment they realize that &lt;em&gt;Adebowale Bello (Backend Intern)&lt;/em&gt; is actually leading a technical team instead of fetching coffee always gives me a bit of joy. It’s the little things!&lt;/p&gt;

&lt;h3&gt;
  
  
  Becoming the Face of Accountability
&lt;/h3&gt;

&lt;p&gt;One of the most jarring shifts was realizing that as a lead, I wasn’t just responsible for my work; I was accountable for my team’s performance. If a project failed, if an integration broke, or if a stakeholder had concerns, I was the first point of contact. This required cultivating a strong problem-solving mindset and not just identifying issues but proactively addressing them before they escalated. Owning both successes and failures became part of the role.&lt;/p&gt;

&lt;h3&gt;
  
  
  Always Having (or Finding) the Answers
&lt;/h3&gt;

&lt;p&gt;Technical leadership doesn’t mean knowing everything; it means knowing how to find answers. Whether it’s debugging a complex issue, optimizing system performance, or justifying a technical decision to stakeholders, I had to be prepared. This required staying updated on industry trends, constantly improving my problem-solving approach, and ensuring my team had the right resources to succeed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Pressure and Expectations
&lt;/h3&gt;

&lt;p&gt;Pressure is inevitable. Juggling deadlines, ensuring the team’s efficiency, and balancing technical and managerial responsibilities required mental resilience. Managing and aligning with leadership’s expectations was just as crucial as managing and ensuring my team had clarity and support. Setting realistic expectations, communicating effectively, and prioritizing tasks helped in keeping the chaos under control.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Culture That Encourages Growth
&lt;/h3&gt;

&lt;p&gt;Beyond my team, the company’s commitment to fostering a culture of continuous learning and innovation has been a key driver in my growth. The environment has encouraged experimentation, provided access to learning resources, and offered opportunities to take on challenging projects that pushed me out of my comfort zone. Having an organization that values professional development has made the transition into leadership smoother and more rewarding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stakeholder and Cross-Functional Collaboration
&lt;/h3&gt;

&lt;p&gt;As a technical lead, my role extended beyond my immediate team. Engaging with product managers, designers, and business executives became routine. Translating technical complexities into digestible information for non-technical stakeholders was a skill I had to hone. Understanding business needs and aligning technical solutions with them was key to driving impact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The journey from an intern to a technical lead has been transformative. The growth has been immense, not just in technical proficiency but in leadership, communication, and decision-making. It’s a role that demands continuous learning, resilience, and adaptability. While the challenges are many, the fulfillment of leading a team, driving impact, and shaping solutions that matter makes it all worthwhile.&lt;/p&gt;

&lt;p&gt;And the learning continues! I strive every day to bring my A-game, improve my skills, and encourage those around me to do the same. For anyone navigating a similar path, embrace the steepness of the climb, it’s where growth happens. And never underestimate the power of a great team and a company that champions growth.&lt;/p&gt;

</description>
      <category>careerdevelopment</category>
      <category>career</category>
    </item>
    <item>
      <title>Introduction to ElasticSearch in Laravel</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Tue, 16 Jul 2024 23:19:28 +0000</pubDate>
      <link>https://forem.com/devbalop/introduction-to-elasticsearch-in-laravel-1e34</link>
      <guid>https://forem.com/devbalop/introduction-to-elasticsearch-in-laravel-1e34</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Elasticsearch is a tool that helps you search and analyze large amounts of information very quickly. Imagine it as a super-fast librarian who can find exactly what you need from a huge collection of books in just a few seconds. When used with Laravel, Elasticsearch makes it easy to add advanced search features to your projects. This article will explain how to integrate Elasticsearch with Laravel, its advantages, disadvantages, and provide some examples of how to use it.&lt;/p&gt;

&lt;p&gt;Think of Elasticsearch as a search engine for websites and apps, similar to how Google works for the internet. Here’s a simple comparison:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Search&lt;/strong&gt;: Helps you find web pages, images, videos, etc from the entire internet quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elasticsearch&lt;/strong&gt;: Helps you find specific information from your website or app's data quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just like Google can instantly give you results for any search query, Elasticsearch can do the same for the data in your website or app. It’s incredibly fast and can handle a lot of data at once, making it ideal for large websites or applications with lots of information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Definition of Elasticsearch
&lt;/h3&gt;

&lt;p&gt;Elasticsearch is a distributed, RESTful search and analytics engine capable of addressing a growing number of use cases. As an open-source search engine, it is built on Apache Lucene and is known for its powerful and flexible search capabilities. Integrating Elasticsearch with Laravel, allows developers to implement advanced search functionalities efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages of Using Elasticsearch with Laravel
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High Performance&lt;/strong&gt;: Elasticsearch is optimized for full-text search and performs complex queries in milliseconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: It can scale horizontally, handling large volumes of data by distributing them across multiple nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Data&lt;/strong&gt;: Provides near real-time search and analytics, which is crucial for applications needing up-to-date information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible Querying&lt;/strong&gt;: Supports a wide range of search capabilities, including fuzzy search, keyword matching, and complex boolean queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community and Documentation&lt;/strong&gt;: As a widely-used tool, Elasticsearch has comprehensive documentation and a large community for support.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Disadvantages of Using Elasticsearch with Laravel
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Setting up and configuring Elasticsearch can be complex compared to traditional SQL databases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Intensive&lt;/strong&gt;: It requires significant memory and CPU resources, especially for large-scale applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Consistency&lt;/strong&gt;: Elasticsearch may not always guarantee immediate consistency, which could be an issue for some applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Curve&lt;/strong&gt;: Requires a learning curve for developers unfamiliar with its querying language and configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Applications of Elasticsearch in Laravel
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce Platforms&lt;/strong&gt;: For product search and filtering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Management Systems&lt;/strong&gt;: To enable powerful content search and indexing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Analytics&lt;/strong&gt;: For analyzing logs, metrics, and monitoring data in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social Networks&lt;/strong&gt;: To implement search functionalities for users, posts, and other entities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise Search&lt;/strong&gt;: For indexing and searching across internal documents and databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Integrating Elasticsearch with Laravel
&lt;/h3&gt;

&lt;p&gt;To integrate Elasticsearch with Laravel, we use Laravel Scout, a driver-based library for adding full-text search to Eloquent models, and the Elasticsearch driver for Laravel Scout.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Install Elasticsearch
&lt;/h4&gt;

&lt;p&gt;First, install Elasticsearch on your local machine or server. Follow the installation instructions from the &lt;a href="https://www.elastic.co/downloads/elasticsearch" rel="noopener noreferrer"&gt;Elasticsearch website&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Install Laravel Scout and Elasticsearch Driver
&lt;/h4&gt;

&lt;p&gt;Run the following commands to install Laravel Scout and the Elasticsearch driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/scout
composer require babenkoivan/scout-elasticsearch-driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Configure Laravel Scout
&lt;/h4&gt;

&lt;p&gt;Publish the Scout configuration file and set the driver to Elasticsearch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Laravel&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;cout&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="s2"&gt;coutServiceProvider"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCOUT_DRIVER=elastic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure Elasticsearch in &lt;code&gt;config/scout.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SCOUT_DRIVER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'algolia'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="s1"&gt;'elasticsearch'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'index'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ELASTICSEARCH_INDEX'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'your_index_name'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s1"&gt;'hosts'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ELASTICSEARCH_HOST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'http://localhost'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Add Searchable Trait to Models
&lt;/h4&gt;

&lt;p&gt;To make a model searchable, add the &lt;code&gt;Searchable&lt;/code&gt; trait to the model class. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Scout\Searchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Searchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toSearchableArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Index Data
&lt;/h4&gt;

&lt;p&gt;Index your existing data using the &lt;code&gt;scout:import&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan scout:import &lt;span class="s2"&gt;"App&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Models&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Post"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Perform Search Queries
&lt;/h4&gt;

&lt;p&gt;Use the &lt;code&gt;search&lt;/code&gt; method to perform search queries on your model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'example search term'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sample Usage
&lt;/h3&gt;

&lt;p&gt;Here’s a simple search implementation in Laravel:&lt;/p&gt;

&lt;h4&gt;
  
  
  Search Form (Blade Template)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"{{ route('posts.search') }}"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"query"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search posts..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Search&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Controller Action
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'posts.search_results'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'posts'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Search Results Blade Template
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;@if($posts-&amp;gt;isEmpty())
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;No posts found.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
@else
    &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
        @foreach($posts as $post)
            &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;{{ $post-&amp;gt;title }}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        @endforeach
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
@endif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Integrating Elasticsearch with Laravel provides powerful and flexible search capabilities that enhance the functionality of any application. Despite the complexity and resource requirements, the benefits of high performance, scalability, and real-time data handling make Elasticsearch a valuable tool for developers. By following the steps outlined above, you can efficiently implement Elasticsearch in your Laravel projects, providing users with a robust search experience.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Comprehensive Guide to Using Observers in Laravel</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Sat, 25 May 2024 16:42:45 +0000</pubDate>
      <link>https://forem.com/devbalop/comprehensive-guide-to-using-observers-in-laravel-5dcf</link>
      <guid>https://forem.com/devbalop/comprehensive-guide-to-using-observers-in-laravel-5dcf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Laravel Observers are a powerful feature that allows you to hook into the lifecycle events of your Eloquent models. By using observers, you can listen for various events that are fired by the model, such as when a model is created, updated, or deleted, and then execute specific logic in response to those events. This helps in keeping your code clean and maintaining the single responsibility principle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lifecycle Events
&lt;/h2&gt;

&lt;p&gt;Observers can listen to the following model events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;retrieved&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;creating&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;created&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;updating&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;updated&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;saving&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;saved&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deleting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deleted&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;restoring&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;restored&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article, I will show a quick use case of sending user authentication credentials to a new user upon profiling. We will create a user model observer that sends an email to the new user when admin creates his profile on the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Observer
&lt;/h2&gt;

&lt;p&gt;To create an observer, you can use the &lt;code&gt;make:observer&lt;/code&gt; Artisan command. For example, to create an observer for the &lt;code&gt;User&lt;/code&gt; model, you would run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:observer UserObserver &lt;span class="nt"&gt;--model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;User
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will generate a new observer class in the &lt;code&gt;app/Observers&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Registering an Observer
&lt;/h2&gt;

&lt;p&gt;To register the observer, you need to add it to the &lt;code&gt;boot&lt;/code&gt; method of one of your service providers, typically the &lt;code&gt;AppServiceProvider&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Observers\UserObserver&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Bootstrap any application services.
 *
 * @return void
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserObserver&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the UserCredentials notification class
&lt;/h2&gt;

&lt;p&gt;Create a notification class to send the email if it doesn't already exist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:notification UserCredentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the UserCredentials notification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Notifications&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Bus\Queueable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Contracts\Queue\ShouldQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Notifications\Messages\MailMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Notifications\Notification&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCredentials&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create a new notification instance.
     *
     * @param string $username
     * @param string $password
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get the notification's delivery channels.
     *
     * @param mixed $notifiable
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'mail'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get the mail representation of the notification.
     *
     * @param mixed $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toMail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MailMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Your account has been created.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Username: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Password: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Thank you for using our application!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Get the array representation of the notification.
     *
     * @param mixed $notifiable
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sample Observer
&lt;/h2&gt;

&lt;p&gt;Here's an example of a &lt;code&gt;UserObserver&lt;/code&gt; that listens for the &lt;code&gt;created&lt;/code&gt; events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Observers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Notifications\UserCredentials&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserObserver&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle the User "created" event.
     *
     * @param  \App\Models\User  $user
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$plainPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserCredentials&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$plainPassword&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

     &lt;span class="cd"&gt;/** Ensure the password is hashed if the create method 
      *  had saved plain text from the controller
      */&lt;/span&gt;

        &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$plainPassword&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Other events can be handled similarly...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using the Observer
&lt;/h2&gt;

&lt;p&gt;Once the observer is registered, it will automatically listen for the specified events on the model. For example, whenever a &lt;code&gt;User&lt;/code&gt; model is created, the corresponding methods in the &lt;code&gt;UserObserver&lt;/code&gt; will be executed, thereby sending the login credential to the created user.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Using Observers
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Observers help in keeping the model and business logic separate. This makes the codebase cleaner and more maintainable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Reusability&lt;/strong&gt;: By using observers, you can reuse the same logic across multiple parts of your application without duplicating code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralized Logic&lt;/strong&gt;: Observers allow you to centralize event-based logic in one place, making it easier to manage and update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Readability&lt;/strong&gt;: With observers, your models are free from additional responsibilities, making them easier to read and understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy Testing&lt;/strong&gt;: Observers can be tested independently of the models, which simplifies the testing process.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Laravel Observers provide a structured and efficient way to handle model events. By leveraging observers, you can keep your codebase clean, maintainable, and adhere to best practices like the single responsibility principle. They are a valuable tool in any Laravel developer's arsenal, promoting better organization and modularization of code.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Unleashing the Power of Method Chaining in PHP</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Tue, 16 Jan 2024 11:22:07 +0000</pubDate>
      <link>https://forem.com/devbalop/unleashing-the-power-of-method-chaining-in-laravel-e5h</link>
      <guid>https://forem.com/devbalop/unleashing-the-power-of-method-chaining-in-laravel-e5h</guid>
      <description>&lt;p&gt;In programming, readability and efficiency are essential. Method chaining is a sophisticated feature that gives your code a hint of both. Imagine writing one neat line of code that could handle a series of operations on an object. That is how method chaining works its magic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Method Chaining?
&lt;/h2&gt;

&lt;p&gt;Method chaining is a technique that allows you to call multiple methods on an object in a single statement. This not only streamlines your code but also enhances its readability. In PHP, method chaining is made possible by designing methods to return the object itself (&lt;code&gt;$this&lt;/code&gt;), enabling subsequent calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;Let's dive into a simple example. Consider a &lt;code&gt;Calculator&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage example:&lt;/span&gt;
&lt;span class="nv"&gt;$calculator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$calculator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getResult&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, each method returns &lt;code&gt;$this&lt;/code&gt;, allowing us to chain subsequent methods. The result is a clear and concise sequence of operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Method Chaining
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Conciseness:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By combining several lines of code into one, method chaining makes your code more readable and concise.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Readability:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The linear structure of method chaining improves code readability. Each method call builds upon the previous one, creating a smooth flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Fluent Interfaces:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using method chaining helps to create interfaces that are fluid. Your code has a natural language feel to it because it reads like a phrase.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Less Temporary Variables:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With method chaining, you often don't need temporary variables to store intermediate results, reducing clutter in your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Configuration:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Method chaining is commonly used in configuration settings. You can set multiple options in a single statement, providing a clear configuration process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setOption1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'value1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setOption2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'value2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setOption3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'value3'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Query Builders:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Database query builders frequently leverage method chaining. Each method call adds a new condition or operation to the query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'column1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'column2'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'condition'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'column1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ASC'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Fluent APIs:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Fluent APIs use method chaining to create expressive and readable interfaces. This is common in libraries and frameworks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'john@example.com'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pitfalls to Avoid
&lt;/h2&gt;

&lt;p&gt;While method chaining is a powerful tool, it's essential to use it judiciously:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Overuse:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Avoid chaining too many methods in a single line. Balance conciseness with readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Complexity:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Be cautious with method chaining in complex logic. Ensure that each method call is clear and doesn't introduce confusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;One useful approach that can greatly enhance the readability and conciseness of your PHP code is method chaining. You may write cleaner, more maintainable code by utilizing this elegant feature to design interfaces that are more expressive and fluid.&lt;/p&gt;

&lt;p&gt;In your next PHP project, consider incorporating method chaining where appropriate. As you unlock the potential of this technique, your code will become not just functional, but a joy to read and maintain.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>optimization</category>
      <category>webdev</category>
    </item>
    <item>
      <title>"Laravel: Real-time Application Data Issue Export Directly To A Slack Channel"</title>
      <dc:creator>Adebowale Bello</dc:creator>
      <pubDate>Sat, 14 Oct 2023 00:43:03 +0000</pubDate>
      <link>https://forem.com/devbalop/laravel-real-time-application-data-issue-export-directly-to-a-slack-channel-7i8</link>
      <guid>https://forem.com/devbalop/laravel-real-time-application-data-issue-export-directly-to-a-slack-channel-7i8</guid>
      <description>&lt;p&gt;User interaction is vital for an application's success. With more users, chances of use case issues arises, thereby creating bad data in your application's db. Addressing these in real-time is crucial. Imagine if your app could proactively report defects or bad data to the team before clients notice. &lt;/p&gt;

&lt;p&gt;In this article, I'll show you how to integrate direct reporting to Slack via a Slack app, streamlining the process.&lt;/p&gt;

&lt;p&gt;In this article, I will cover;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Creating A Slack App&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating sample command that handles recognising failed payments with reference to a simple &lt;strong&gt;E-commerce payment system&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Creating a slack app&lt;/strong&gt;&lt;br&gt;
To get started, go to &lt;a href="https://api.slack.com/apps/"&gt;Slack&lt;/a&gt; and click on the "Create New App" button. Then, select the first option as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5bdsuqgxytu0vpvg618.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5bdsuqgxytu0vpvg618.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the application name, choose a workspace, and then press the "Create App" button to save the form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoips57x2ztuqhnm9xlq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoips57x2ztuqhnm9xlq.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating our app, choose the "Incoming Webhooks" option and toggle it on the next screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpras2igiz9j1o3d8y2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpras2igiz9j1o3d8y2b.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the bottom of the page and select "Add New Webhook to Workspace." Then, on the following screen, pick a channel and click "Allow."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiazzj4t4um2pkjb61h4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiazzj4t4um2pkjb61h4f.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slack will generate a webhook URL. Copy it and paste it into your app's .env file as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;FAILED_PAYMENT_SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://hooks.slack.com/services/xxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Creating sample command&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Laravel, commands are custom, reusable scripts that perform specific tasks within the application. They can be executed via the command line interface (CLI) and are useful for automating tasks, such as database migrations, scheduled jobs, and custom operations.&lt;/p&gt;

&lt;p&gt;In Laravel, custom commands are typically stored in the &lt;code&gt;app/Console/Commands&lt;/code&gt; directory. You can create a new command using the Artisan CLI or by manually creating a new PHP file in that directory.&lt;/p&gt;

&lt;p&gt;Here's an example of a basic command:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Creating a Command&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can create a command using Artisan. Open your terminal and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;php artisan make:command ExportFailedPayments&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This will generate a new command file named &lt;code&gt;ExportFailedPayments.php&lt;/code&gt; in the &lt;code&gt;app/Console/Commands&lt;/code&gt; directory.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Sample Command Code&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Open the generated &lt;code&gt;ExportFailedPayments.php&lt;/code&gt; file and you'll find something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Console\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Http&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExportFailedPayments&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'export:failed-payments'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Export failed payments to CSV and send to server'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Generate CSV data (replace this with your actual logic)&lt;/span&gt;
        &lt;span class="nv"&gt;$csvData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'order_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'payment_id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="c1"&gt;// Add more rows as needed&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$csvFilePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app/failed_payments.csv'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$csvFilePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$csvData&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;fputcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$row&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

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

        &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Daily Failed Payment Report:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;
        File: &amp;lt;"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$csvFilePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"|Download CSV&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'FAILED_PAYMENT_SLACK_WEBHOOK_URL'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Replace with your actual slack webhook url.&lt;/span&gt;


        &lt;span class="c1"&gt;// Clean up: Delete the local CSV file&lt;/span&gt;
        &lt;span class="nb"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$csvFilePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Using the Command&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now execute this command in the terminal using its signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan &lt;span class="nb"&gt;export&lt;/span&gt;:failed-payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will trigger the &lt;code&gt;handle&lt;/code&gt; method, and any logic you place there will be executed.&lt;/p&gt;

&lt;p&gt;Remember, this is a basic example. Commands can perform a wide range of tasks, from database operations to complex data processing. But we are only referencing a failed payment export instance in this article.&lt;/p&gt;

&lt;p&gt;In E-commerce, it is important to reconcile failed payment as early as possible, so in this article, I will show you how to create a cron job that schedules this command above to run as often as you want it to.&lt;/p&gt;

&lt;p&gt;To schedule this command to run at e.g (5pm every day), you'll need to add an entry to your Laravel scheduler. Open the &lt;code&gt;App\Console\Kernel.php&lt;/code&gt; file and add the following code to the &lt;code&gt;$commands&lt;/code&gt; array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;// ... other commands ...&lt;/span&gt;
    &lt;span class="nc"&gt;Commands\ExportFailedPayments&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, in the &lt;code&gt;schedule&lt;/code&gt; method of the same file, add the following line to schedule the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Schedule&lt;/span&gt; &lt;span class="nv"&gt;$schedule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... other scheduled tasks ...&lt;/span&gt;

    &lt;span class="nv"&gt;$schedule&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'export:failed-payments'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;dailyAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'17:00'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This will run the command at 5:00 PM&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, your &lt;code&gt;ExportFailedPayments&lt;/code&gt; command will be scheduled to run at 5:00 PM every day. Make sure your server is correctly configured to handle Laravel's scheduled tasks (using cron or task scheduler depending on your server environment).&lt;/p&gt;

&lt;p&gt;Below, you'll find an example of the report based on the focus of this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqzw1bjg2thyl7tlwh9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqzw1bjg2thyl7tlwh9g.png" alt="Image description" width="505" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope this was helpful. Thanks for dropping by!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>slack</category>
      <category>webdev</category>
      <category>ecommerce</category>
    </item>
  </channel>
</rss>
