<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lakashya Upadhyay</title>
    <description>The latest articles on DEV Community by Lakashya Upadhyay (@lakshya-addweb).</description>
    <link>https://dev.to/lakshya-addweb</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%2F3570369%2Fbcfe352e-879a-4c2d-bcb0-96cfa8aa29b9.jpeg</url>
      <title>DEV Community: Lakashya Upadhyay</title>
      <link>https://dev.to/lakshya-addweb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakshya-addweb"/>
    <language>en</language>
    <item>
      <title>Common Mistakes Laravel Developers Make (And How to Avoid Them)</title>
      <dc:creator>Lakashya Upadhyay</dc:creator>
      <pubDate>Fri, 27 Mar 2026 08:23:53 +0000</pubDate>
      <link>https://dev.to/addwebsolutionpvtltd/common-mistakes-laravel-developers-make-and-how-to-avoid-them-3oem</link>
      <guid>https://dev.to/addwebsolutionpvtltd/common-mistakes-laravel-developers-make-and-how-to-avoid-them-3oem</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Controllers should coordinate, not decide.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every Laravel developer, from juniors to seasoned engineers, has written code that felt “good enough” but created performance bottlenecks, deep technical debt, or hard‑to‑debug bugs months later. Laravel’s expressive API makes it easy to ship fast, but it also makes it easy to fall into common anti‑patterns.&lt;/p&gt;

&lt;p&gt;This guide walks through the most frequent mistakes Laravel developers make in production, explains why they’re harmful, and shows how to refactor them into clean, maintainable structures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avoid putting business logic in controllers; move it into services, actions, or domain classes.&lt;/li&gt;
&lt;li&gt;Use Eloquent relationships, eager loading, and proper indexing to prevent N+1 queries.&lt;/li&gt;
&lt;li&gt;Organize your code with proper folders, route groups, and naming conventions.&lt;/li&gt;
&lt;li&gt;Separate validation from controllers and reuse it via Form Requests or validation rules.&lt;/li&gt;
&lt;li&gt;Use migrations, tests, and documentation to keep your app scalable and on‑team‑friendly.&lt;/li&gt;
&lt;li&gt;Treat database design, authentication, and security as first‑class concerns, not afterthoughts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Index
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why This Matters&lt;/li&gt;
&lt;li&gt;Mistake 1: Putting Too Much Logic in Controllers&lt;/li&gt;
&lt;li&gt;Mistake 2: Ignoring Eloquent Relationships and N+1 Queries&lt;/li&gt;
&lt;li&gt;Mistake 3: Poor Database Design and Indexing&lt;/li&gt;
&lt;li&gt;Mistake 4: Not Using Form Requests or Validation Properly&lt;/li&gt;
&lt;li&gt;Mistake 5: Ignoring Migrations and Model Structure&lt;/li&gt;
&lt;li&gt;Mistake 6: Messy Routes and Poor Naming Conventions&lt;/li&gt;
&lt;li&gt;Mistake 7: Overusing Helper/Static Methods and Global Helpers&lt;/li&gt;
&lt;li&gt;Mistake 8: Skipping Tests and Documentation&lt;/li&gt;
&lt;li&gt;Mistake 9: Hard‑coding Logic in Migrations or Seeders&lt;/li&gt;
&lt;li&gt;Mistake 10: Poor Error Handling and Logging&lt;/li&gt;
&lt;li&gt;Frequently Asked Questions (FAQs)&lt;/li&gt;
&lt;li&gt;Interesting Facts &amp;amp; Stats&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Why This Matters
&lt;/h2&gt;

&lt;p&gt;Laravel is designed to help you ship fast while keeping your codebase sane. But if you ignore structure, performance, and maintainability, your app can quickly become a “Laravel monolith” with tangled controllers, slow queries, and brittle validation.&lt;/p&gt;

&lt;p&gt;Common mistakes Laravel developers make often look harmless at first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A controller method that grows from 10 to 100 lines.&lt;/li&gt;
&lt;li&gt;A route file that crosses 500 lines.&lt;/li&gt;
&lt;li&gt;A model that eagerly loads every relation on every query.
These small decisions compound over time, leading to slower performance, harder debugging, and more expensive refactoring later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide helps you avoid the most common pitfalls and build Laravel apps that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Readable to other developers&lt;/li&gt;
&lt;li&gt;Testable with clear separation of concerns&lt;/li&gt;
&lt;li&gt;Scalable as the user base and feature set grow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Mistake 1: Putting Too Much Logic in Controllers
&lt;/h2&gt;

&lt;p&gt;Controllers are meant to handle HTTP concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepting requests&lt;/li&gt;
&lt;li&gt;Running validation&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returning responses&lt;br&gt;
When you put business logic directly in controllers, you end up with:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fat controllers anyone is afraid to touch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplicated logic across multiple controller methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hard‑to‑test code that depends on the HTTP request&lt;br&gt;
Example of the mistake:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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;SubscriptionController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&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;upgrade&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;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;user&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;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isPremium&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;back&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;withErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'You are already premium.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$price&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;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'plan'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'annual'&lt;/span&gt;
            &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$gateway&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;StripeGateway&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$gateway&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$price&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;role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'premium'&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;premium_until&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;now&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;addYear&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;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nf"&gt;event&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;UserUpgraded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&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;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/dashboard'&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;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Move charge and subscription logic into a &lt;code&gt;SubscriptionService&lt;/code&gt; or &lt;code&gt;SubscriptionAction&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Keep the controller action thin and focused on the request/response pipeline.
&lt;/li&gt;
&lt;/ul&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;SubscriptionController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&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;upgrade&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="kt"&gt;UpgradeSubscriptionAction&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;plan&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;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'plan'&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;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;failed&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;back&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;withErrors&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;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;message&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;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/dashboard'&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;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business logic is reusable across APIs, commands, and jobs.&lt;/li&gt;
&lt;li&gt;Easier to unit test the subscription logic without touching HTTP.&lt;/li&gt;
&lt;li&gt;Cleaner diffs and easier on‑boarding for new team members.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Mistake 2: Ignoring Eloquent Relationships and N+1 Queries
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Eloquent is powerful, but misuse kills performance.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many Laravel developers fetch data manually instead of using Eloquent relationships. This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;N+1 queries (one query per related record)&lt;/li&gt;
&lt;li&gt;Slow page loads&lt;/li&gt;
&lt;li&gt;Database bottlenecks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of the mistake:&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;all&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;$posts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Each access triggers a separate query&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define relationships in your models (User belongsToMany Posts, etc.).&lt;/li&gt;
&lt;li&gt;Use with() to eager load related data.
&lt;/li&gt;
&lt;/ul&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;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user'&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;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// No extra query&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use select() to limit columns when you don’t need the full model.&lt;/li&gt;
&lt;li&gt;Avoid all() on large tables; paginate instead with paginate().&lt;/li&gt;
&lt;li&gt;Use tools like laravel-debugbar or clockwork to detect N+1 queries early.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Mistake 3: Poor Database Design and Indexing
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Bad database design will always be your bottleneck.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many Laravel apps start with poorly normalized tables, missing foreign keys, or no indexes on frequently queried columns. This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slow queries&lt;/li&gt;
&lt;li&gt;Complex joins and filters in PHP instead of SQL&lt;/li&gt;
&lt;li&gt;Inconsistent or denormalized data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Common anti‑patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storing JSON in a single column instead of proper relationships&lt;/li&gt;
&lt;li&gt;Using integers for IDs but not defining foreign‑key constraints&lt;/li&gt;
&lt;li&gt;Not indexing columns used in where, order, or join clauses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Laravel migrations to define tables, indexes, and foreign keys.&lt;/li&gt;
&lt;li&gt;Normalize your data where it makes sense (e.g., users → posts → comments).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Index frequently filtered columns:&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;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&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="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&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;constrained&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster queries as datasets grow&lt;/li&gt;
&lt;li&gt;Easier to maintain data consistency&lt;/li&gt;
&lt;li&gt;Cleaner, more predictable Eloquent relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Mistake 4: Not Using Form Requests or Validation Properly
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Validation should be reusable, not copy‑pasted.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Laravel’s validation is powerful, but it’s often embedded directly in controllers as inline arrays or repeated in multiple methods.&lt;/p&gt;

&lt;p&gt;Example of the mistake:&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;UserController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&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;update&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;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'age'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'nullable|integer|min:18'&lt;/span&gt;&lt;span class="p"&gt;,&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&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;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'age'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'nullable|integer|min:18'&lt;/span&gt;&lt;span class="p"&gt;,&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Form Request classes:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:request UserStoreRequest
php artisan make:request UserUpdateRequest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;UserStoreRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&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;rules&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;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|unique:users,email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'age'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'nullable|integer|min:18'&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inject the form request into your controller:&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UserStoreRequest&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;$validated&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;validated&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validation rules are reusable and centralized&lt;/li&gt;
&lt;li&gt;You can add custom validation logic or authorization inside the form request&lt;/li&gt;
&lt;li&gt;Controllers stay lean and focused&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Mistake 5: Ignoring Migrations and Model Structure
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“They removed the model directory after the first migration.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Migrations are Laravel’s way to version‑control your database. Ignoring them or using them incorrectly leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Divergent schemas across environments&lt;/li&gt;
&lt;li&gt;Manual SQL changes in production&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broken deployments&lt;br&gt;
Common mistakes:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not using down() methods in migrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Writing business logic inside migration files (e.g., looping through users and updating them)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Skipping foreign keys or using unsigned() on integer foreign keys&lt;br&gt;
How to fix it:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Always define proper foreign keys:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&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;constrained&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use rollback‑safe migrations with clear up() and down() methods.&lt;/li&gt;
&lt;li&gt;Avoid complex business logic in migrations; move it to seeders or jobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Best practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat migrations as “immutable” after they’re pushed to production.&lt;/li&gt;
&lt;li&gt;Use Schema::table() for alterations, not Schema::dropIfExists() for simple changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Mistake 6: Messy Routes and Poor Naming Conventions
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Routes are the contract of your app.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Laravel’s routing system is powerful, but it’s easy to end up with a monolithic routes/web.php file and inconsistently named routes.&lt;/p&gt;

&lt;p&gt;Common issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mixing API and web routes in one file&lt;/li&gt;
&lt;li&gt;Not using route groups (prefix, middleware, namespace)&lt;/li&gt;
&lt;li&gt;Using inconsistent route names like userShow, showUser, show_user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split routes into:

&lt;ul&gt;
&lt;li&gt;routes/web.php (HTML pages)&lt;/li&gt;
&lt;li&gt;routes/api.php (REST or JSON endpoints)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Use route groups to apply middleware and prefixes:
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth'&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;prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserController&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="s1"&gt;'index'&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;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin.users.index'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Route&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="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserController&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="s1"&gt;'store'&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;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin.users.store'&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;ul&gt;
&lt;li&gt;Follow consistent naming conventions (e.g.,
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;resource_route_name&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;snake_case&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users.'&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;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserController&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="s1"&gt;'index'&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;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users/{user}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserController&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="s1"&gt;'show'&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;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'show'&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;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routes are easier to scan and maintain&lt;/li&gt;
&lt;li&gt;Route names are predictable for other developers&lt;/li&gt;
&lt;li&gt;Auth and middleware configuration is centralized&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Mistake 7: Overusing Helper/Static Methods and Global Helpers
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Helper methods are helpers, not your business logic.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many Laravel apps accumulate global helper functions in &lt;code&gt;app/Helpers&lt;/code&gt; or &lt;code&gt;config/helpers.php.&lt;/code&gt; This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hidden dependencies and hard‑to‑trace behavior&lt;/li&gt;
&lt;li&gt;Testing nightmare (no dependency injection)&lt;/li&gt;
&lt;li&gt;Spaghetti‑style code scattered across functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use services, actions, or managers instead of global helpers.&lt;/li&gt;
&lt;li&gt;Use dependency injection where possible.
For example, instead of:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/Helpers/general.php&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;calculateDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;,&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="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&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;Use a service:&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;DiscountService&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;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$price&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="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&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;Inject it into your controller or action:&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;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;checkout&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="kt"&gt;DiscountService&lt;/span&gt; &lt;span class="nv"&gt;$discount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$price&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;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$discounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$discount&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear dependencies and easier testing&lt;/li&gt;
&lt;li&gt;Reusable across services, jobs, and controllers&lt;/li&gt;
&lt;li&gt;Easier to refactor or replace logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Mistake 8: Skipping Tests and Documentation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Tests are your safety net.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Skipping tests leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fear of refactoring&lt;/li&gt;
&lt;li&gt;More bugs in production&lt;/li&gt;
&lt;li&gt;Longer on‑boarding for new developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write feature tests for critical user flows.&lt;/li&gt;
&lt;li&gt;Write unit tests for business logic and services.
Use Laravel’s built‑in testing helpers:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test_user_can_upgrade_subscription&lt;/span&gt;&lt;span class="p"&gt;()&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;=&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;factory&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;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&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="nf"&gt;actingAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'subscriptions.upgrade'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'plan'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'annual'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertRedirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/dashboard'&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="nf"&gt;assertTrue&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;fresh&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;isPremium&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;Best practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use expectsDatabaseTransactions() for database‑intensive tests.&lt;/li&gt;
&lt;li&gt;Keep your tests fast and focused.&lt;/li&gt;
&lt;li&gt;Add high‑level documentation for architecture, routes, and key classes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. Mistake 9: Hard‑coding Logic in Migrations or Seeders
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Migrations are not meant to run business logic.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;People sometimes write loops, call services, or send notifications inside migrations or seeders. This is dangerous because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrations are meant to be repeatable and safe to roll back&lt;/li&gt;
&lt;li&gt;Running business logic here can break future deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use migrations only for:

&lt;ul&gt;
&lt;li&gt;Schema changes&lt;/li&gt;
&lt;li&gt;Simple data seeding (if needed)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Move business logic into:

&lt;ul&gt;
&lt;li&gt;Artisan commands&lt;/li&gt;
&lt;li&gt;Jobs&lt;/li&gt;
&lt;li&gt;Seeders with proper rollback support&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Example:&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:command MigrateOldUserSubscriptions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run it explicitly instead of hiding it in a migration.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migrations stay predictable and safe&lt;/li&gt;
&lt;li&gt;Business logic can be retried or rolled back cleanly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. Mistake 10: Poor Error Handling and Logging
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Exceptions are information, not noise.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ignoring error handling and logging in Laravel apps leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Silent failures&lt;/li&gt;
&lt;li&gt;Difficult debugging in production&lt;/li&gt;
&lt;li&gt;Unpredictable behavior after exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use try/catch blocks where appropriate.&lt;/li&gt;
&lt;li&gt;Use Log::error(), Log::info(), or report() to log errors.&lt;/li&gt;
&lt;li&gt;Configure app/Exceptions/Handler.php to:

&lt;ul&gt;
&lt;li&gt;Report critical errors to services like Sentry, Bugsnag, or LogRocket&lt;/li&gt;
&lt;li&gt;Transform exceptions into user‑friendly messages&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$exception&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;$exception&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;CustomException&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Log or notify specific teams&lt;/span&gt;
        &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'slack'&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exception&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;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier debugging and faster incident response&lt;/li&gt;
&lt;li&gt;Better visibility into production issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. Frequently Asked Questions (FAQs)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q. Should I always move logic from controllers to services?&lt;/strong&gt;&lt;br&gt;
A. Yes, if it’s reusable business logic. Keep controllers focused on HTTP concerns and use services, actions, or domain classes for the rest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Is it okay to keep small apps without tests?&lt;/strong&gt;&lt;br&gt;
A. For small prototypes, maybe. But even tiny apps benefit from a basic test suite once they go to production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Can I mix web and API routes in one file?&lt;/strong&gt;&lt;br&gt;
A. Technically yes, but it’s cleaner to separate them into web.php and api.php with proper prefixing and middleware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Are migrations really necessary for small changes?&lt;/strong&gt;&lt;br&gt;
A. Yes, especially after going live. Migrations help keep your team and environment in sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. How do I know if my app has N+1 queries?&lt;/strong&gt;&lt;br&gt;
A. Use tools like laravel-debugbar or clockwork to analyse queries or enable Laravel’s built‑in query logging in development.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Interesting Facts &amp;amp; Stats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Well-structured Laravel apps with services, form requests, and proper Eloquent usage can reduce controller code by 40-60% in larger projects. Source: &lt;a href="https://laravel.com/docs/eloquent-resources" rel="noopener noreferrer"&gt;https://laravel.com/docs/eloquent-resources&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Teams that consistently use migrations and tests spend 25-35% less time debugging in production compared to teams that don’t.
Source: &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;https://martinfowler.com/articles/practical-test-pyramid.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Avoiding N+1 queries often reduces page load time by 2-10x for list-style pages with relationships.Source: &lt;a href="https://laravel.com/docs/eloquent-relationships#eager-loading" rel="noopener noreferrer"&gt;https://laravel.com/docs/eloquent-relationships#eager-loading&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel’s Form Request system and built-in validation rules have become industry standards for clean, maintainable validation logic in web frameworks.Source: &lt;a href="https://laravel.com/docs/validation" rel="noopener noreferrer"&gt;https://laravel.com/docs/validation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  14. Conclusion
&lt;/h2&gt;

&lt;p&gt;Laravel is a powerful framework that encourages fast development, but it also amplifies the impact of bad habits. Common mistakes like fat controllers, poor database design, and ignoring migrations can slow your app and your team over time.&lt;/p&gt;

&lt;p&gt;By consistently:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Moving business logic out of controllers&lt;/li&gt;
&lt;li&gt;Using Eloquent properly and avoiding N+1 queries&lt;/li&gt;
&lt;li&gt;Organizing routes, migrations, and helpers&lt;/li&gt;
&lt;li&gt;Writing tests and proper logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You turn Laravel’s “easy to start” advantage into a long‑term maintenance win.&lt;/p&gt;

&lt;p&gt;Clean, maintainable Laravel code is not about syntax alone; it’s about structure, separation of concerns, and respecting the framework’s conventions. Stick to these patterns, and you’ll avoid most of the common pitfalls Laravel developers face in production.&lt;/p&gt;

&lt;p&gt;About the Author: &lt;em&gt;Lakashya is a full‑stack Laravel developer at &lt;a href="https://www.addwebsolution.com/our-capabilities/laravel-development-agency" rel="noopener noreferrer"&gt;AddWeb Solution&lt;/a&gt; specializing in scalable, real‑time applications with PHP and modern frontends.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel Documentation. (2025). Best Practices. 
&lt;a href="https://laravel.com/docs/12.x%E2%80%8B" rel="noopener noreferrer"&gt;https://laravel.com/docs/12.x​&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel.io. (2026). Common Laravel Mistakes I See in Production. &lt;a href="https://laravel.io/articles/common-laravel-mistakes-i-see-in-production-and-how-to-avoid-them" rel="noopener noreferrer"&gt;https://laravel.io/articles/common-laravel-mistakes-i-see-in-production-and-how-to-avoid-them&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Laravel Daily. (2025). Laravel: 9 Typical Mistakes Juniors Make. &lt;a href="https://laraveldaily.com/post/laravel-typical-mistakes-juniors-make" rel="noopener noreferrer"&gt;https://laraveldaily.com/post/laravel-typical-mistakes-juniors-make&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravelbestpractices</category>
      <category>laravelmistakes</category>
      <category>phpdevelopment</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Building Real-time Notifications with Laravel Broadcasting and React</title>
      <dc:creator>Lakashya Upadhyay</dc:creator>
      <pubDate>Mon, 02 Mar 2026 08:40:43 +0000</pubDate>
      <link>https://dev.to/addwebsolutionpvtltd/building-real-time-notifications-with-laravel-broadcasting-and-react-4k3b</link>
      <guid>https://dev.to/addwebsolutionpvtltd/building-real-time-notifications-with-laravel-broadcasting-and-react-4k3b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"Your users don't want to refresh to know what just happened."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Real-time notifications keep your users in sync with what's happening in your app the moment it happens. Whether it's a new club event, a gallery image, or a direct message, Laravel Broadcasting combined with React (or Firebase push) gives you a clean, scalable way to deliver these updates instantly.&lt;/p&gt;

&lt;p&gt;This guide walks you through building real-time notifications in Laravel, wiring them to a React frontend (and optionally Firebase), and structuring everything in a way that fits enterprise-grade apps&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use Laravel Broadcasting for server-side event streaming over WebSockets&lt;/li&gt;
&lt;li&gt;Use Laravel Echo in React to subscribe to channels and listen for events&lt;/li&gt;
&lt;li&gt;Use private channels for per-user notifications and proper authorizationUse Laravel notifications when you want a unified API (database, broadcast, mail, etc.)&lt;/li&gt;
&lt;li&gt;Use Firebase Cloud Messaging for OS-level push notifications on web/mobile&lt;/li&gt;
&lt;li&gt;Real-time notifications improve UX, engagement, and responsiveness of your Laravel apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Index
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Real-time Notifications Matter&lt;/li&gt;
&lt;li&gt;How Laravel Broadcasting Works&lt;/li&gt;
&lt;li&gt;Broadcasting vs Firebase Notifications&lt;/li&gt;
&lt;li&gt;Setting Up Broadcasting in Laravel&lt;/li&gt;
&lt;li&gt;Creating a Broadcastable Notification/Event&lt;/li&gt;
&lt;li&gt;Wiring React with Laravel Echo&lt;/li&gt;
&lt;li&gt;Implementing User-specific (Private) Notifications&lt;/li&gt;
&lt;li&gt;Using Firebase for Push Notifications&lt;/li&gt;
&lt;li&gt;Common Mistakes to Avoid&lt;/li&gt;
&lt;li&gt;FAQs&lt;/li&gt;
&lt;li&gt;Interesting Facts &amp;amp; Stats&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Why Real-time Notifications Matter
&lt;/h2&gt;

&lt;p&gt;Real-time notifications ensure your app pushes updates to users the moment something important occurs, instead of waiting for manual refreshes or cron-based checks&lt;br&gt;
This is critical for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Engagement:&lt;/strong&gt; Users stay hooked when they see new events, bookings, or messages instantly&lt;br&gt;
&lt;strong&gt;- Productivity:&lt;/strong&gt; Admins can react faster to changes like new registrations or approvals&lt;br&gt;
&lt;strong&gt;- UX:&lt;/strong&gt; Your app feels modern and responsive, like chat apps or live dashboards&lt;br&gt;
&lt;strong&gt;- Scalability:&lt;/strong&gt; WebSockets reduce polling overhead and server load for frequent updates&lt;/p&gt;

&lt;p&gt;Today, Laravel's built-in broadcasting API, combined with WebSockets or Pusher-style drivers, makes building these real-time experiences straightforward&lt;/p&gt;
&lt;h2&gt;
  
  
  2. How Laravel Broadcasting Works (The Basics)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“A real-time notification system is the heartbeat of a responsive web application.”- Technical Lead&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Laravel Broadcasting lets you "broadcast" server-side events over WebSockets (or Pusher-like services) so your frontend can listen in real time.&lt;/p&gt;

&lt;p&gt;Core pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Broadcast events: PHP classes (often implementing ShouldBroadcast) that describe what to send to the front end&lt;/li&gt;
&lt;li&gt;Channels: Named streams (public, private, or presence) your front end subscribes to&lt;/li&gt;
&lt;li&gt;Broadcasters: Drivers like pusher, ably, redis + laravel-websockets, etc., that handle WebSocket delivery&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Laravel Echo: JavaScript client that connects to your broadcaster and listens to events in the browser/React app&lt;br&gt;
Example event outline:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend: Broadcast an event (e.g., NewNotificationCreated) on channel notifications or App.Models.User.{id}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Frontend: Echo.channel('notifications').listen('NewNotificationCreated', callback)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Laravel reconstructs the payload into JSON and sends it over the WebSocket connection automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  3. Broadcasting vs Firebase Notifications
&lt;/h2&gt;

&lt;p&gt;Both Broadcasting and Firebase deliver real-time messages, but they solve slightly different problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ary33ssmo01vl8ogxim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ary33ssmo01vl8ogxim.png" alt=" " width="588" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Table 1: Comparison of Laravel Broadcasting and Firebase FCM&lt;br&gt;
A solid architecture often uses both: broadcasting for in-app real-time UI and FCM for OS-level push when the user is not actively on the page.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Setting Up Broadcasting in Laravel
&lt;/h2&gt;

&lt;p&gt;Laravel ships with broadcasting out of the box; you just pick a driver and configure it.&lt;br&gt;
Steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure broadcast driver in .env:

&lt;ul&gt;
&lt;li&gt;BROADCAST_DRIVER=pusher (or ably, redis, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Configure your broadcaster in config/broadcasting.php (keys, cluster, host, etc.)&lt;/li&gt;
&lt;li&gt;Enable the BroadcastServiceProvider if not already enabled (for channels.php)&lt;/li&gt;
&lt;li&gt;Define channels in routes/channels.php:

&lt;ul&gt;
&lt;li&gt;Public channel: Broadcast::channel('notifications', fn () =&amp;gt; true);&lt;/li&gt;
&lt;li&gt;Private channel: Broadcast::channel('App.Models.User.{id}', fn ($user, id)=&amp;gt;(int)user-&amp;gt;id === (int)$id);&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you use Laravel WebSockets or a self-hosted server, you configure a pusher-compatible app ID/key/secret pointing to your WebSocket host and port.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Creating a Broadcastable Notification/Event
&lt;/h2&gt;

&lt;p&gt;There are two main ways to broadcast from Laravel: events and notifications.&lt;br&gt;
Events approach:&lt;br&gt;
Generate an event:&lt;br&gt;
php artisan make:event ClubEventCreated&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ClubEventCreated implements ShouldBroadcast
{
    public $clubEvent;

    public function __construct($clubEvent)
    {
        $this-&amp;gt;clubEvent = $clubEvent;
    }

    public function broadcastOn(): array
    {
        return [
            new Channel('club-events'), // Public
            new PrivateChannel('App.Models.User.' . $this-&amp;gt;clubEvent-&amp;gt;user_id), // User-specific
        ];
    }

    public function broadcastWith(): array
    {
        return [
            'message' =&amp;gt; 'New club event: ' . $this-&amp;gt;clubEvent-&amp;gt;name,
            'event' =&amp;gt; $this-&amp;gt;clubEvent,
        ];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dispatch: event(new ClubEventCreated($eventModel));&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notifications approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Laravel's Notification system and add broadcast to via().&lt;br&gt;
Laravel automatically broadcasts a notification to a channel App.Models.User.{id}.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NewClubEventNotification extends Notification implements ShouldBroadcast
{
    public $clubEvent;

    public function __construct($clubEvent)
    {
        $this-&amp;gt;clubEvent = $clubEvent;
    }

    public function via($notifiable): array
    {
        return ['database', 'broadcast'];
    }

    public function toBroadcast($notifiable): BroadcastMessage
    {
        return new BroadcastMessage([
            'message' =&amp;gt; 'New club event created!',
            'event_id' =&amp;gt; $this-&amp;gt;clubEvent-&amp;gt;id,
        ]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send: $user-&amp;gt;notify(new NewClubEventNotification($clubEvent));&lt;br&gt;
This gives you database + real-time delivery with almost no extra wiring.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Wiring React with Laravel Echo
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;“Users shouldn’t refresh to see updates,real-time notifications should do the talking.” - Frontend Specialist&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the frontend, you use Laravel Echo plus a connector like pusher-js to subscribe to channels and listen for events in React.&lt;br&gt;
Key steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install libraries in your React app (e.g., laravel-echo and pusher-js)&lt;/li&gt;
&lt;li&gt;Create a shared Echo instance (for example in a separate echo.js or service file)&lt;/li&gt;
&lt;li&gt;Configure with broadcaster: 'pusher', key, wsHost, wsPort, forceTLS, etc.&lt;/li&gt;
&lt;li&gt;In a React component, subscribe to channels and attach listeners in useEffect, cleaning up on unmount
Example pattern:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useEffect } from 'react';
import Echo from 'laravel-echo'; // Your Echo instance

const NotificationsComponent = ({ userId }) =&amp;gt; {
  useEffect(() =&amp;gt; {
    // Public channel
    Echo.channel('club-events')
      .listen('ClubEventCreated', (e) =&amp;gt; {
        console.log('New event:', e.message);
        // Update UI state
      });

    // Private per-user notifications
    Echo.private(`App.Models.User.${userId}`)
      .notification((notification) =&amp;gt; {
        console.log('Personal notification:', notification.message);
        // Show toast or update badge
      });

    return () =&amp;gt; {
      Echo.leaveChannel('club-events');
      Echo.leaveChannel(`App.Models.User.${userId}`);
    };
  }, [userId]);

  return &amp;lt;div&amp;gt;Your notifications here&amp;lt;/div&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This pattern keeps your React code clean and focused on updating state when events arrive.&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Implementing User-specific (Private) Notifications
&lt;/h2&gt;

&lt;p&gt;For real-world apps, you rarely show the same notification to everyone; you want user-specific or role-specific notifications.&lt;br&gt;
Laravel makes this easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use private channels like App.Models.User.{id} for per-user streams&lt;/li&gt;
&lt;li&gt;Write a channel authorization callback in routes/channels.php to ensure only the owner can subscribe&lt;/li&gt;
&lt;li&gt;Use Laravel Notifications with broadcast channel, which automatically targets App.Models.User.{id}&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example channels.php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
    return (int) $user-&amp;gt;id === (int) $id;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the React side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subscribe to Echo.private(App.Models.User.${userId}) once the user is authenticated&lt;/li&gt;
&lt;li&gt;Use the .notification(...) helper to receive any broadcast notification&lt;/li&gt;
&lt;li&gt;Update a notifications list, counter badge, or toast component when data arrives
This maps perfectly to scenarios like "show a red dot on the bell icon when there is a new club event for this user".&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Using Firebase for Push Notifications
&lt;/h2&gt;

&lt;p&gt;Broadcasting covers in-app real-time, but sometimes you want OS-level push notifications via Firebase Cloud Messaging (FCM).&lt;br&gt;
Common flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure a Firebase project and enable FCM&lt;/li&gt;
&lt;li&gt;Include the Firebase JS SDK in your web app and request notification permission from the user&lt;/li&gt;
&lt;li&gt;Retrieve and store the user's FCM token in your Laravel users table&lt;/li&gt;
&lt;li&gt;From Laravel, send push notifications using FCM HTTP APIs or a package (e.g., via a notification channel)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ClubEventPushNotification extends Notification
{
    public function via($notifiable): array
    {
        return ['fcm']; // Assuming a package like laravel-fcm
    }

    public function toFcm($notifiable)
    {
        return FcmMessage::create('New Club Event')
            -&amp;gt;withBody('Check out the new event!')
            -&amp;gt;withData(['event_id' =&amp;gt; $this-&amp;gt;event-&amp;gt;id]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When a new gallery image is uploaded, broadcast via Laravel for users currently on the site and send an FCM push for users in the background&lt;/li&gt;
&lt;li&gt;When a booking is about to expire, trigger queued notifications that hit FCM and update in-app badges via broadcasting at the same time
Combining FCM with Laravel Broadcasting gives you a full real-time story: in-tab updates plus system-level pushes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Mixing up event and notification names in Echo listeners (they must match the class name or notification structure)&lt;/li&gt;
&lt;li&gt;Forgetting to start or configure your WebSocket server (like laravel-websockets or echo server)&lt;/li&gt;
&lt;li&gt;Using public channels for sensitive data instead of private channels with authorization callbacks&lt;/li&gt;
&lt;li&gt;Not cleaning up Echo subscriptions in React components, causing memory leaks or duplicate listeners&lt;/li&gt;
&lt;li&gt;Ignoring token lifecycle for FCM (tokens change and need to be refreshed and updated on the backend)&lt;/li&gt;
&lt;li&gt;Avoiding these issues will save you hours of debugging and strange "it works sometimes" bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  10. FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q. Do I need Pusher to use Laravel Broadcasting?&lt;/strong&gt;&lt;br&gt;
No. Laravel supports multiple broadcasters, including self-hosted Laravel WebSockets and Redis-based setups that emulate Pusher's protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. When should I use events vs notifications for broadcasting?&lt;/strong&gt;&lt;br&gt;
Use broadcastable events when you just need a fire-and-forget message; use notifications when you also want database/email/SMS plus real-time broadcasting under a single API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. How do I secure user-specific notifications?&lt;/strong&gt;&lt;br&gt;
Use private channels (App.Models.User.{id}) with proper channel authorization and Echo.private on the frontend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Can I use React, Vue, or plain JS with Laravel Echo?&lt;/strong&gt;&lt;br&gt;
Yes. Echo is framework-agnostic and can be used in React, Vue, Next.js, or even vanilla JavaScript, as long as you instantiate it correctly in your client-side code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Is Firebase required for real-time notifications?&lt;/strong&gt;&lt;br&gt;
No. WebSockets via Broadcasting and Echo are enough for in-app real-time updates. Firebase is only needed if you want OS-level push notifications outside of the active browser tab or app.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Interesting Facts &amp;amp; Stats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Laravel's broadcasting system is built to integrate directly with its event and notification APIs, so you can reuse the same infrastructure for in-app events, queues, and real-time updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Articles and tutorials on WebSockets and real-time Laravel apps highlight significant reductions in server load when replacing long polling with proper WebSocket broadcasting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Guides on Laravel + Next.js and Laravel + WebSockets show that real-time notification architectures scale well when you offload to WebSockets servers and use broadcasting events efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Documentation for Laravel notifications emphasizes how broadcasting and the notification system together simplify multi-channel delivery (database, mail, Slack, broadcast) with minimal code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Firebase FCM is widely used as a backend for mobile and web push notifications, and it integrates well with Laravel as long as you manage tokens and server keys securely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  12. Conclusion
&lt;/h2&gt;

&lt;p&gt;Real-time notifications transform your Laravel app from "request-response only" to a live, interactive experience.&lt;/p&gt;

&lt;p&gt;By combining Laravel Broadcasting, Echo, and a React frontend (plus optional Firebase), you can deliver user-specific updates instantly, keep your UI always fresh, and still maintain a clean, testable backend architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] Laravel Documentation. (2025). Broadcasting. &lt;a href="https://laravel.com/docs/12.x/broadcasting" rel="noopener noreferrer"&gt;https://laravel.com/docs/12.x/broadcasting&lt;/a&gt;&lt;br&gt;
[2] Rumpel, C. (2020). Laravel Real-Time Notifications. Retrieved from &lt;a href="https://christoph-rumpel.com/2020/11/laravel-real-time-notifications" rel="noopener noreferrer"&gt;https://christoph-rumpel.com/2020/11/laravel-real-time-notifications&lt;/a&gt;&lt;br&gt;
[3] Laravel Documentation. (2025). Notifications. &lt;a href="https://laravel.com/docs/12.x/notifications" rel="noopener noreferrer"&gt;https://laravel.com/docs/12.x/notifications&lt;/a&gt;&lt;br&gt;
[4] Laravel-Docs. (2024). Event Broadcasting. Retrieved from &lt;a href="https://laravel-docs.readthedocs.io/en/latest/broadcasting/" rel="noopener noreferrer"&gt;https://laravel-docs.readthedocs.io/en/latest/broadcasting/&lt;/a&gt;&lt;br&gt;
[5] Dev.to. (2025). Implementing Real-time Notifications Using Laravel WebSockets. Retrieved from &lt;a href="https://dev.to/prateekshaweb/implementing-real-time-notifications-using-laravel-websockets-and-nextjs-a-complete-guide-1a2l"&gt;https://dev.to/prateekshaweb/implementing-real-time-notifications-using-laravel-websockets-and-nextjs-a-complete-guide-1a2l&lt;/a&gt;&lt;br&gt;
[6] iFlair. (2025). Real-Time Push Notifications in Laravel with Firebase. &lt;a href="https://www.iflair.com/real-time-push-notifications-in-laravel-with-firebase/" rel="noopener noreferrer"&gt;https://www.iflair.com/real-time-push-notifications-in-laravel-with-firebase/&lt;/a&gt;&lt;br&gt;
[7] Pusher. (2024). Build Online Presence into Your Laravel App. Retrieved from &lt;a href="https://pusher.com/tutorials/online-presence-laravel/" rel="noopener noreferrer"&gt;https://pusher.com/tutorials/online-presence-laravel/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About the Author: &lt;em&gt;Lakashya is a web developer at &lt;a href="https://www.addwebsolution.com/our-capabilities/laravel-development-agency" rel="noopener noreferrer"&gt;AddWebSolution&lt;/a&gt;, building scalable apps with PHP &amp;amp; React. Sharing ideas, code, and creativity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravelbroadcasting</category>
      <category>laravelecho</category>
      <category>react</category>
      <category>realtimeapps</category>
    </item>
    <item>
      <title>Laravel Event Sourcing: From Aggregates to Projectors</title>
      <dc:creator>Lakashya Upadhyay</dc:creator>
      <pubDate>Tue, 27 Jan 2026 13:08:33 +0000</pubDate>
      <link>https://dev.to/addwebsolutionpvtltd/laravel-event-sourcing-from-aggregates-to-projectors-3lj8</link>
      <guid>https://dev.to/addwebsolutionpvtltd/laravel-event-sourcing-from-aggregates-to-projectors-3lj8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Your app’s history is as important as its current state.”- Every Enterprise Developer Ever&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Event sourcing is a powerful architectural pattern that treats every change in your application as an event. If you’re building complex systems where audit trails, historical data, and state changes are critical, Laravel event sourcing is a game-changer.&lt;/p&gt;

&lt;p&gt;This guide walks you through mastering Laravel event sourcing, from setting up aggregates and projectors to building scalable, auditable applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use aggregates for business logic and state management&lt;/li&gt;
&lt;li&gt;Use projectors for read models and reporting&lt;/li&gt;
&lt;li&gt;Use reactors for side effects&lt;/li&gt;
&lt;li&gt;Version events and plan for migration&lt;/li&gt;
&lt;li&gt;Ensure events are immutable and idempotent&lt;/li&gt;
&lt;li&gt;Event sourcing makes your Laravel apps auditable, scalable, and maintainable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Index
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Laravel Event Sourcing Matters&lt;/li&gt;
&lt;li&gt;How Laravel Event Sourcing Works&lt;/li&gt;
&lt;li&gt;Aggregates vs Projectors&lt;/li&gt;
&lt;li&gt;Setting Up Event Sourcing in Laravel&lt;/li&gt;
&lt;li&gt;Creating Aggregates&lt;/li&gt;
&lt;li&gt;Building Projectors&lt;/li&gt;
&lt;li&gt;Handling Events and Event Queries&lt;/li&gt;
&lt;li&gt;Using Reactors&lt;/li&gt;
&lt;li&gt;Event Versioning and Migration&lt;/li&gt;
&lt;li&gt;Common Mistakes to Avoid&lt;/li&gt;
&lt;li&gt;FAQs&lt;/li&gt;
&lt;li&gt;Interesting Facts &amp;amp; Stats&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Why Laravel Event Sourcing Matters
&lt;/h2&gt;

&lt;p&gt;Event sourcing ensures every action in your application is recorded as an immutable event. This makes it possible to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reconstruct any state at any point in time&lt;/li&gt;
&lt;li&gt;Audit and debug changes easily&lt;/li&gt;
&lt;li&gt;Build powerful reporting and analytics&lt;/li&gt;
&lt;li&gt;Scale read and write operations independently
Without event sourcing, complex applications often lose historical context and become hard to maintain. Laravel, with packages like Spatie’s laravel-event-sourcing, makes it easy to adopt this pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. How Laravel Event Sourcing Works (The Basics)
&lt;/h2&gt;

&lt;p&gt;Event sourcing in Laravel revolves around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Events: Represent changes (e.g., UserCreated, OrderPlaced)&lt;/li&gt;
&lt;li&gt;Aggregates: Entities that record and replay events&lt;/li&gt;
&lt;li&gt;Projectors: Classes that update read models based on events&lt;/li&gt;
&lt;li&gt;Reactors: Classes that trigger side effects (e.g., sending emails)
Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$user-&amp;gt;create(['name' =&amp;gt; 'John'])-&amp;gt;recordThat(new UserCreated(['name' =&amp;gt; 'John']));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each event is stored, and the aggregate’s state is rebuilt by replaying events.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Aggregates vs Projectors
&lt;/h2&gt;

&lt;p&gt;Aggregates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hold business logic and state&lt;/li&gt;
&lt;li&gt;Record and replay events to rebuild state&lt;/li&gt;
&lt;li&gt;Ensure consistency
Projectors:&lt;/li&gt;
&lt;li&gt;Listen to events and update read models (e.g., database tables)&lt;/li&gt;
&lt;li&gt;Enable fast queries and reporting&lt;/li&gt;
&lt;li&gt;Decouple read and write logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Setting Up Event Sourcing in Laravel
&lt;/h2&gt;

&lt;p&gt;Install the Spatie package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require spatie/laravel-event-sourcing

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

&lt;/div&gt;



&lt;p&gt;Publish the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider="Spatie\EventSourcing\EventSourcingServiceProvider"

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

&lt;/div&gt;



&lt;p&gt;Create your event store migration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:migration create_stored_events_table

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

&lt;/div&gt;



&lt;p&gt;Configure your event store model and repository as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Creating Aggregates
&lt;/h2&gt;

&lt;p&gt;Generate an aggregate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:aggregate UserAggregate

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserAggregate extends AggregateRoot
{
    public function createUser(array $attributes)
    {
        $this-&amp;gt;recordThat(new UserCreated($attributes));
        return $this;
    }
}

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

&lt;/div&gt;



&lt;p&gt;Aggregates handle business logic and record events.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Building Projectors
&lt;/h2&gt;

&lt;p&gt;Generate a projector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:projector UserProjector

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserProjector extends Projector
{
    public function onUserCreated(UserCreated $event)
    {
        User::create($event-&amp;gt;attributes);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Projectors update read models for fast queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Handling Events and Event Queries
&lt;/h2&gt;

&lt;p&gt;Events are stored in the event store. To query events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$events = StoredEvent::where('aggregate_uuid', $uuid)-&amp;gt;get();

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

&lt;/div&gt;



&lt;p&gt;Replay events to rebuild state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$aggregate = UserAggregate::retrieve($uuid);

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

&lt;/div&gt;



&lt;p&gt;This allows you to reconstruct any state from events.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Using Reactors
&lt;/h2&gt;

&lt;p&gt;Reactors trigger side effects (e.g., sending notifications):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserReactor extends Reactor
{
    public function onUserCreated(UserCreated $event)
    {
        Mail::to($event-&amp;gt;attributes['email'])-&amp;gt;send(new WelcomeEmail());}}

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

&lt;/div&gt;



&lt;p&gt;Reactors keep business logic and side effects separate.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Event Versioning and Migration
&lt;/h2&gt;

&lt;p&gt;When events change, version them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class UserCreatedV2 extends UserCreated
{
    // new structure
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Migrate old events to new versions to maintain compatibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Not versioning events&lt;/li&gt;
&lt;li&gt;Storing mutable state in events&lt;/li&gt;
&lt;li&gt;Overloading aggregates with too much logic&lt;/li&gt;
&lt;li&gt;Ignoring idempotency in event handling&lt;/li&gt;
&lt;li&gt;Not planning for event store growth&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  11. FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q. When should I use event sourcing?&lt;/strong&gt;&lt;br&gt;
When you need audit trails, historical data, or complex state changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Can I mix event sourcing with traditional models?&lt;/strong&gt;&lt;br&gt;
Yes, use event sourcing for critical parts and traditional models elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. How do I handle event store growth?&lt;/strong&gt;&lt;br&gt;
Use database partitioning, archiving, and optimization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. What if an event is missing?&lt;/strong&gt;&lt;br&gt;
Replay events to rebuild state or fix the event stream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Can I use event sourcing for small apps?&lt;/strong&gt;&lt;br&gt;
Only if you need the benefits; otherwise, it adds complexity.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Interesting Facts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;- Laravel’s event sourcing concepts&lt;/strong&gt;&lt;br&gt;
This covers why event sourcing works well for audit trails and fits Laravel/CQRS architectures.&lt;a href="https://laravel-news.com/event-sourcing-in-laravel" rel="noopener noreferrer"&gt;https://laravel-news.com/event-sourcing-in-laravel&lt;/a&gt; Laravel News&lt;br&gt;
&lt;strong&gt;- MoldStud article noting debugging and audit trail benefits&lt;/strong&gt;&lt;br&gt;
Discusses how using event sourcing helps trace state changes and can cut debugging time by replaying events. &lt;a href="https://moldstud.com/articles/p-managing-data-consistency-in-laravel-microservices-best-practices-and-strategies" rel="noopener noreferrer"&gt;https://moldstud.com/articles/p-managing-data-consistency-in-laravel-microservices-best-practices-and-strategies&lt;/a&gt; MoldStud&lt;br&gt;
&lt;strong&gt;- Spatie Laravel Event Sourcing documentation&lt;/strong&gt;&lt;br&gt;
Explains how event sourcing in Laravel supports auditability and reporting needs.&lt;a href="https://spatie.be/docs/laravel-event-sourcing/v7/introduction" rel="noopener noreferrer"&gt;https://spatie.be/docs/laravel-event-sourcing/v7/introduction&lt;/a&gt; Spatie&lt;br&gt;
&lt;strong&gt;- Event sourcing &amp;amp; CQRS patterns overview (general context)&lt;/strong&gt;&lt;br&gt;
Shows broader adoption of these patterns and why they’re used in event-driven architectures.&lt;a href="https://medium.com/techartifact-technology-learning/event-driven-architecture-with-cqrs-event-sourcing-bdded2f3c595" rel="noopener noreferrer"&gt;https://medium.com/techartifact-technology-learning/event-driven-architecture-with-cqrs-event-sourcing-bdded2f3c595&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Conclusion
&lt;/h2&gt;

&lt;p&gt;Event sourcing is a powerful pattern for building robust, auditable, and scalable Laravel applications. By using aggregates, projectors, and reactors, you can decouple business logic, reporting, and side effects. Whether you’re building a CRM, banking app, or e-commerce platform, event sourcing ensures your system is maintainable and future-proof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the Author:&lt;/strong&gt; &lt;em&gt;Lakashya is a web developer at &lt;a href="https://www.addwebsolution.com/our-capabilities/laravel-development-agency" rel="noopener noreferrer"&gt;AddWebSolution&lt;/a&gt;, building scalable apps with PHP &amp;amp; React. Sharing ideas, code, and creativity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laraveleventsourcing</category>
      <category>aggregates</category>
      <category>laraveldevelopers</category>
      <category>cqrs</category>
    </item>
    <item>
      <title>MySQL Index Optimization for Complex Laravel Queries</title>
      <dc:creator>Lakashya Upadhyay</dc:creator>
      <pubDate>Fri, 07 Nov 2025 10:02:33 +0000</pubDate>
      <link>https://dev.to/addwebsolutionpvtltd/mysql-index-optimization-for-complex-laravel-queries-1abc</link>
      <guid>https://dev.to/addwebsolutionpvtltd/mysql-index-optimization-for-complex-laravel-queries-1abc</guid>
      <description>&lt;p&gt;A developer's Guide for optimization. It will be very helpful if you’re going to create a DB from Scratch.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Premature optimization is the root of all evil but ignoring indexing is even worse." -Donald Kunth&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Analyze first, then optimize. Use Laravel’s query logs and MySQL’s EXPLAIN command before adding indexes.&lt;/li&gt;
&lt;li&gt;Choose selective columns. Index fields often used in WHERE, JOIN, and ORDER BY clauses.&lt;/li&gt;
&lt;li&gt;Composite indexes are powerful but order matters the most selective column comes first. Avoid over indexing. Too many indexes slow down writes and take up unnecessary storage.&lt;/li&gt;
&lt;li&gt;Database indexing is essential for scaling Laravel applications; the right indexes can improve query speed by 10x or more.&lt;/li&gt;
&lt;li&gt;Index maintenance is ongoing. As your data grows, periodically review and adjust indexes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Index
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Why Your Laravel App is Slow&lt;/li&gt;
&lt;li&gt;What Are Indexes Really?&lt;/li&gt;
&lt;li&gt;Finding and Fixing Slow Queries&lt;/li&gt;
&lt;li&gt;Creating the Right Indexes&lt;/li&gt;
&lt;li&gt;Fixing Common Laravel Performance Issues&lt;/li&gt;
&lt;li&gt;Real World Examples&lt;/li&gt;
&lt;li&gt;Quick Wins You Can Implement Today&lt;/li&gt;
&lt;li&gt;Monitoring and Measuring Query Performance&lt;/li&gt;
&lt;li&gt;What Not to Do&lt;/li&gt;
&lt;li&gt;Key Takeaways&lt;/li&gt;
&lt;li&gt;FAQs&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why Your Laravel App is Slow (And How to Fix It)
&lt;/h2&gt;

&lt;p&gt;After building dozens of Laravel applications, I've seen the same performance issues over and over. Your app works fine with 100 users, but crashes with 10,000. This is due to Poor database indexing.&lt;/p&gt;

&lt;p&gt;Let me share what I've learned from optimizing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics You Need to Know
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. What Are Indexes Really?&lt;/strong&gt;&lt;br&gt;
Just think of indexes like a phone book. Without indexing, you'd flip through every page to find "Lakashya Upadhyay." With an index, you jump straight to the S section. That's exactly what database indexes do for your queries&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This query without an index scans EVERY row
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM users WHERE email = 'lakashya@addwebsoution.in'; 

-- With an index on email, it finds the row instantly 
CREATE INDEX idx_users_email ON users(email);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. The Performance Results will be:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster reads, slower writes.&lt;/strong&gt; Every index you add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Speeds up SELECT queries&lt;/li&gt;
&lt;li&gt;Slows down INSERT/UPDATE operations&lt;/li&gt;
&lt;li&gt;Takes extra storage space
See,You have to Choose wisely if the table is mostly used for fetch the Data Then Indexing will be the best option&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;"Good indexes make queries fly; bad ones make servers cry."&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Finding Your Slow Queries
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Laravel Query Log&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Add this to your controller temporarily
DB::enableQueryLog();

// Run your slow page
$users = User::with('posts')-&amp;gt;where('status', 'active')-&amp;gt;get();

// See what's really happening
dd(DB::getQueryLog());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. The EXPLAIN Command&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPLAIN SELECT u.name, COUNT(p.id) as post_count 
FROM users u 
LEFT JOIN posts p ON u.id = p.user_id 
WHERE u.status = 'active' 
GROUP BY u.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;type: ALL (table scan - bad)&lt;/li&gt;
&lt;li&gt;type: index or type: ref (good)&lt;/li&gt;
&lt;li&gt;High rows count (needs optimization)
This is a basic Example of how a query looks good but if we are talking about large data sets then a small indexes can make the filtering and query fast a lot that we can notice it with human eyes as well&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating the Right Indexes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Laravel Migrations Made Simple&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Schema::table('users', function (Blueprint $table) {
    // Single column - for WHERE clauses
    $table-&amp;gt;index('email');

    // Composite index - column order matters!
    $table-&amp;gt;index(['status', 'created_at']);

    // Foreign keys (Laravel creates these automatically)
    $table-&amp;gt;foreign('company_id')-&amp;gt;references('id')-&amp;gt;on('companies');});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. The Golden Rules of Composite Indexes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order matters!&lt;/strong&gt; Put the most selective column first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Good: status has few values, created_at has many
$table-&amp;gt;index(['status', 'created_at']);

// Bad: created_at first makes the index less effective
$table-&amp;gt;index(['created_at', 'status']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fixing Common Laravel Performance Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. The N+1 Query&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This executes 101 queries (1 + 100)
$users = User::all(); // 1 query
foreach ($users as $user) {
    echo $user-&amp;gt;posts-&amp;gt;count(); // 100 queries
}

// This executes 1 query
$users = User::withCount('posts')-&amp;gt;get();
foreach ($users as $user) {
    echo $user-&amp;gt;posts_count; // Uses preloaded data
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Inefficient WHERE Clauses&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Bad - can't use indexes
User::whereRaw('YEAR(created_at) = 2024')-&amp;gt;get();

// Good - uses index on created_at
User::whereBetween('created_at', ['2024-01-01', '2024-12-31'])-&amp;gt;get();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Missing Relationship Indexes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Schema::create('posts', function (Blueprint $table) {
    $table-&amp;gt;id();
    $table-&amp;gt;foreignId('user_id')-&amp;gt;constrained(); // Auto-indexed
    $table-&amp;gt;string('title');
    $table-&amp;gt;text('content');
    $table-&amp;gt;string('status');
    $table-&amp;gt;timestamps();

    // Add this for common queries
    $table-&amp;gt;index(['user_id', 'status']);
    $table-&amp;gt;inindex(['status', 'created_at']);
});
$table-&amp;gt;index(['user_id', 'status']);
 $table-&amp;gt;index(['status', 'created_at']);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Example
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. E-commerce Product Search&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The query
Product::where('category_id', 5)
       -&amp;gt;where('status', 'active')
       -&amp;gt;where('price', '&amp;lt;=', 100)
       -&amp;gt;orderBy('created_at', 'desc')
       -&amp;gt;get();

// The index
Schema::table('products', function (Blueprint $table) {
    $table-&amp;gt;index(['category_id', 'status', 'price']);
    $table-&amp;gt;index(['status', 'created_at']); // For ordering});

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. User Dashboard with Posts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Common query pattern
$user = User::with(['posts' =&amp;gt; function($query) {
    $query-&amp;gt;where('status', 'published')
          -&amp;gt;orderBy('created_at', 'desc')
          -&amp;gt;limit(10);
}])-&amp;gt;find(1);

// Required indexes
Schema::table('posts', function (Blueprint $table) {
    $table-&amp;gt;index(['user_id', 'status', 'created_at']);
});

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Quick Wins You Can Implement Today
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Add Indexes for Common Filters&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// If you filter by status everywhere
$table-&amp;gt;index('status');

// If you sort by created_at often
$table-&amp;gt;index('created_at');

// If you do both together
$table-&amp;gt;index(['status', 'created_at']);

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Use Database Transactions for Bulk Operations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB::transaction(function () {
    foreach ($data as $item) {
        User::create($item); }});

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitoring Your Success
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Simple Query Time Logging&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// In AppServiceProvider::boot()
DB::listen(function ($query) {
    if ($query-&amp;gt;time &amp;gt; 1000) { // Over 1 second
        Log::warning('Slow query', [
            'sql' =&amp;gt; $query-&amp;gt;sql,
            'time' =&amp;gt; $query-&amp;gt;time . 'ms'
        ]);
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What NOT to Do
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Don't Over-Index&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Bad - too many indexes
$table-&amp;gt;index('name');
$table-&amp;gt;index('email');
$table-&amp;gt;index(['name', 'email']);
$table-&amp;gt;index(['email', 'name']); // Redundant!

// Good - strategic indexing
$table-&amp;gt;unique('email');
$table-&amp;gt;index(['name', 'email']); // Covers both columns

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Don't Index Low-Selectivity Columns&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Bad - gender has only 2-3 values
$table-&amp;gt;index('gender');

// Good - email is unique per row
$table-&amp;gt;index('email');

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

&lt;/div&gt;



&lt;p&gt;Doing Column Indexing is good approach but make sure use indexing for the field which don't have multiple values just like above example of gender field.Use Indexing for fields which don’t contain common values in it&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Fast apps don’t happen by accident; they happen by design  and indexing is part of that design."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Measure first&lt;/strong&gt; - Use query logs and EXPLAIN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index strategically&lt;/strong&gt; - Focus on WHERE, JOIN, and ORDER BY columns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the order&lt;/strong&gt; - Most selective column first in composite indexes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor continuously&lt;/strong&gt; - Set up slow query alerts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test everything&lt;/strong&gt; - Indexes can sometimes hurt performance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Reference
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Most Common Indexes You Need&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Users table
$table-&amp;gt;unique('email');
$table-&amp;gt;index('status');
$table-&amp;gt;index(['status', 'created_at']);

// Posts table
$table-&amp;gt;index(['user_id', 'status']);
$table-&amp;gt;index(['status', 'created_at']);
$table-&amp;gt;index('slug');

// Orders table
$table-&amp;gt;index(['user_id', 'status']);
$table-&amp;gt;index(['status', 'created_at']);
$table-&amp;gt;index('order_number');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Essential Laravel Query Optimizations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Eager loading
User::with('posts', 'comments')-&amp;gt;get();

// Select specific columns
User::select('id', 'name', 'email')-&amp;gt;get();
// Use exists() for boolean checks
$hasActivePosts = Post::where('user_id', $id)-&amp;gt;where('status', 'active')-&amp;gt;exists();

// Chunk large datasets
User::chunk(1000, function($users) {
    // Process users});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start with these basics, measure your improvements, and slowly and gradually we will achieve an environment where the system gets well optimized and easy to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q. What’s the best way to find slow queries in Laravel?&lt;/strong&gt;&lt;br&gt;
     Use DB::enableQueryLog() during development or set up a listener &lt;br&gt;
     in  AppServiceProvider to log queries taking more than 1000ms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Should I index every column used in WHERE clauses?&lt;/strong&gt;&lt;br&gt;
     No. Only index columns with high selectivity (many unique values). Avoid&lt;br&gt;
     indexing low-selectivity columns like gender or status with few distinct values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. How do I test if an index is helping?&lt;/strong&gt;&lt;br&gt;
     Use the EXPLAIN command in MySQL and compare query execution times&lt;br&gt;
     before and after creating the index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Can too many indexes hurt performance?&lt;/strong&gt;&lt;br&gt;
    Yes. Each index must be updated during INSERT and UPDATE operations, which &lt;br&gt;
    can slow write-heavy tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q. Do Laravel migrations automatically create indexes for foreign keys?&lt;/strong&gt;&lt;br&gt;
    Yes. When you use $table-&amp;gt;foreignId()-&amp;gt;constrained(), &lt;br&gt;
    Laravel automatically indexes that column.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interesting Facts &amp;amp; Stats
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Database performance accounts for nearly 70% of backend bottlenecks in web applications. Source: &lt;a href="https://www.percona.com/blog/" rel="noopener noreferrer"&gt;Percona Performance Blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Proper indexing can reduce query time by up to 95%. Source: &lt;a href="https://www.mysql.com/why-mysql/performance/" rel="noopener noreferrer"&gt;MySQL Performance Blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The N+1 query problem is responsible for up to 80% of unnecessary queries in unoptimized Laravel apps. Source: &lt;a href="https://laravel-news.com/" rel="noopener noreferrer"&gt;Laravel News&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Optimizing your Laravel application starts with understanding your database queries. Proper MySQL indexing is not just a technical detail it’s the foundation for a fast, scalable, and maintainable application. By strategically adding indexes to high-selectivity columns, using composite indexes wisely, and monitoring query performance, you can achieve massive improvements in read efficiency without compromising write operations. &lt;br&gt;
Combine this with Laravel-specific best practices like eager loading, query chunking, and avoiding N+1 queries, and you’ll create an environment where your application can handle growth smoothly. Remember: measure first, index smartly, and monitor continuously performance doesn’t happen by accident; it happens by design.&lt;/p&gt;

&lt;p&gt;About the Author: &lt;em&gt;Lakashya is a web developer at &lt;a href="https://www.addwebsolution.com/our-capabilities/laravel-development-agency" rel="noopener noreferrer"&gt;AddWebSolution&lt;/a&gt;, building scalable apps with PHP &amp;amp; React. Sharing ideas, code, and creativity.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laraveloptimization</category>
      <category>mysqlindexing</category>
      <category>webperf</category>
      <category>laraveldevelopers</category>
    </item>
  </channel>
</rss>
