<?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: Muhamad Sulaiman</title>
    <description>The latest articles on DEV Community by Muhamad Sulaiman (@msulaimanmisri).</description>
    <link>https://dev.to/msulaimanmisri</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%2F622984%2Fac23261b-571e-4e58-be95-b7a96ec1efc5.jpeg</url>
      <title>DEV Community: Muhamad Sulaiman</title>
      <link>https://dev.to/msulaimanmisri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msulaimanmisri"/>
    <language>en</language>
    <item>
      <title>How I Smashed Image Compression in Laravel Using Node.js</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sun, 24 May 2026 12:32:07 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/how-i-smashed-image-compression-in-laravel-using-nodejs-4pgb</link>
      <guid>https://dev.to/msulaimanmisri/how-i-smashed-image-compression-in-laravel-using-nodejs-4pgb</guid>
      <description>&lt;p&gt;Hey everyone! I’ve been learning more deeply about Node.js recently, and instead of studying it in isolation, I wanted to use it to solve a real problem inside the project that I've been working on.&lt;/p&gt;

&lt;p&gt;One of the functions that I need to build is an image compression. But these functions are not developed 100% in Node.js; instead, they are inside my Laravel app.&lt;/p&gt;

&lt;p&gt;One issue kept showing up: image uploads are huge, and processing them directly during a normal Laravel request quickly becomes expensive. So I tried a hybrid approach. Laravel for the application flow, and Node.js with Sharp for the heavy image work.&lt;/p&gt;

&lt;p&gt;This setup ended up being one of the most practical architecture experiments I’ve done in a while.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem
&lt;/h2&gt;

&lt;p&gt;In many Laravel apps, users upload images straight from their phones or from Designers. Those files can easily be several megabytes each, and once you start resizing, converting, and compressing them, the request can become much heavier than it looks.&lt;/p&gt;

&lt;p&gt;The first version of this problem is simple: the upload works, but the response gets slower. The second version is worse: if several users upload at the same time, the application starts spending too much time on image processing instead of serving the rest of the app.&lt;/p&gt;

&lt;p&gt;That was the point where I stopped asking, “How do I make PHP do this?” and started asking, “What should Laravel do, and what should it delegate?”&lt;/p&gt;

&lt;p&gt;While I'm studying Node.js, out of the blue, I'm thinking... "Why don't I pass the heavy work to compress the image by using Node.js?"&lt;/p&gt;

&lt;p&gt;And I've made it. I create the logic and execute it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I moved it to a queue
&lt;/h2&gt;

&lt;p&gt;The biggest improvement was not Node.js alone. It was moving the image optimization work into a queued job.&lt;/p&gt;

&lt;p&gt;Laravel queues are designed for time-intensive tasks, so the application can return a faster response while the heavy work continues in the background. In other words, the controller no longer needs to wait around doing expensive image work before responding to the user.&lt;/p&gt;

&lt;p&gt;That changed the architecture completely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Laravel handles validation, persistence, and job dispatching.&lt;/li&gt;
&lt;li&gt;The queue handles background execution.&lt;/li&gt;
&lt;li&gt;Node.js with Sharp handles image transformation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation feels much more natural than trying to do everything inside one request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Sharp
&lt;/h2&gt;

&lt;p&gt;I chose Sharp because it is a high-speed Node.js image processing library that uses libvips under the hood, and it supports common web image formats like JPEG, PNG, WebP, GIF, and AVIF. Its installation guide also provides prebuilt binaries for many common platforms, which makes it practical to use in real deployments instead of feeling like a purely experimental tool.&lt;/p&gt;

&lt;p&gt;For this use case, Sharp gave me exactly what I needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize oversized uploads.&lt;/li&gt;
&lt;li&gt;Convert to WebP.&lt;/li&gt;
&lt;li&gt;Lower storage usage.&lt;/li&gt;
&lt;li&gt;Keep the worker focused on one job only.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The architecture
&lt;/h2&gt;

&lt;p&gt;I now think about this flow in three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Laravel controller&lt;/strong&gt; receives the upload and stores the original file temporarily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laravel queue job&lt;/strong&gt; gets dispatched for background processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js script&lt;/strong&gt; runs Sharp to resize and convert the image.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So Laravel still owns the application flow, but it no longer performs the expensive image manipulation inside the request itself. That is the part that made the solution feel production-friendly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I kept Node.js isolated
&lt;/h2&gt;

&lt;p&gt;I also kept the Node.js worker code inside its own &lt;code&gt;scripts/&lt;/code&gt; directory with its own &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Could Sharp be installed at the Laravel root? Sometimes yes. But I preferred isolation because the root &lt;code&gt;package.json&lt;/code&gt; usually belongs to frontend tooling such as Vite, Tailwind, Vue, or React, while this worker is backend-oriented and has a different responsibility.&lt;/p&gt;

&lt;p&gt;Keeping the worker separate gave me three benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clearer ownership of dependencies.&lt;/li&gt;
&lt;li&gt;Cleaner deployment steps.&lt;/li&gt;
&lt;li&gt;Less mental overhead when maintaining the project later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of mixing everything together, the project now has a small, focused Node environment whose only job is image optimization.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel-project/
├── app/Http/Controllers/ImageController.php
├── app/Jobs/OptimizeImageJob.php
├── scripts/
│   ├── optimize.js
│   ├── package.json
│   └── .gitignore
└── storage/app/public/optimized/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Controller flow
&lt;/h2&gt;

&lt;p&gt;The controller became much simpler. Its job is no longer to optimize the file immediately. It only stores what is needed and dispatches the background job.&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;StoreImageRequest&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;validated&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'image'&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;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'private/uploads'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// You can extract this to services later.&lt;/span&gt;
    &lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'folder'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'senior-leadership'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'original_path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'queued'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nc"&gt;OptimizeImageJob&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'senior-leadership'&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;response&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;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Image uploaded successfully and queued for optimization.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'queued'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;202&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;That felt much better architecturally. The request stays focused on application flow, and the expensive work happens later.&lt;/p&gt;




&lt;h2&gt;
  
  
  The queued job
&lt;/h2&gt;

&lt;p&gt;This is where Laravel and Node.js meet.&lt;/p&gt;

&lt;p&gt;Laravel jobs can run asynchronously through the queue system, and Laravel also supports passing serialized model data into jobs cleanly. That makes the job layer a natural place to hand the file over to an external worker process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Jobs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Bus\Queueable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Contracts\Queue\ShouldQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Bus\Dispatchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Queue\InteractsWithQueue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Queue\SerializesModels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Symfony\Component\Process\Process&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OptimizeImageJob&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ShouldQueue&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Dispatchable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;InteractsWithQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SerializesModels&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;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;Image&lt;/span&gt; &lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$folder&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$inputPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;original_path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$outputFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storage_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app/public/optimized/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;is_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outputFolder&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$outputFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mo"&gt;0755&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$process&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;Process&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'node'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nf"&gt;base_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'scripts/optimize.js'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nv"&gt;$inputPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$outputFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;isSuccessful&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'failed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'error_message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getErrorOutput&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getOutput&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;

            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;\RuntimeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Image optimization failed.'&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="nb"&gt;json_decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$process&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getOutput&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'optimized'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'optimized_path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'optimized/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'filename'&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;I prefer this over doing the work directly in the controller because it is easier to retry, easier to monitor, and easier to scale later.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Node.js worker
&lt;/h2&gt;

&lt;p&gt;The Node.js side stays intentionally small.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[,,&lt;/span&gt; &lt;span class="nx"&gt;inputPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outputFolder&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;compressImage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputPath&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputFolder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.webp`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;withoutEnlargement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;webp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputPath&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outputPath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unlinkSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.webp`&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;compressImage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I like this part because it does one thing only: optimize the image and return a machine-readable result.&lt;/p&gt;




&lt;h2&gt;
  
  
  What improved
&lt;/h2&gt;

&lt;p&gt;After switching to this design, I got improvements in the areas that actually mattered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Better request responsiveness&lt;/strong&gt; because the optimization no longer runs during the normal HTTP request path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner separation of concerns&lt;/strong&gt; because Laravel owns app logic and the worker owns image processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower storage usage&lt;/strong&gt; because the output is resized and converted to WebP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safer failure handling&lt;/strong&gt; because a failed optimization becomes a job failure, not a broken user request.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;p&gt;This approach is not free of trade-offs.&lt;/p&gt;

&lt;p&gt;You are now maintaining two runtimes in one project: PHP and Node.js. You also need queue workers running properly in each environment, and Laravel supports multiple queue backends like database, Redis, and SQS, depending on how you want to operate the system.&lt;/p&gt;

&lt;p&gt;So I would not use this pattern for every app. But for applications that deal with large uploads or frequent image processing, it feels like a very practical split.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;As someone still learning Node.js, this was a great reminder that learning sticks better when it solves a real problem.&lt;/p&gt;

&lt;p&gt;Laravel remained the application brain. The queue became the handoff layer. Node.js with Sharp became the specialist worker.&lt;/p&gt;

&lt;p&gt;And honestly, that combination felt much more scalable than forcing the whole workflow into a single request.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>javascript</category>
      <category>laravel</category>
    </item>
    <item>
      <title>SDD is now my go-to when developing a Website / Software</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Tue, 19 May 2026 14:33:19 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/sdd-is-now-my-go-to-when-developing-a-website-software-4feh</link>
      <guid>https://dev.to/msulaimanmisri/sdd-is-now-my-go-to-when-developing-a-website-software-4feh</guid>
      <description>&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%2Ffxoa8ic06uiudio1gzpt.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%2Ffxoa8ic06uiudio1gzpt.png" alt="vibe-coding-vs-sdd" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, I ran an experiment across several of the projects I’ve been building. The focus of that experiment was simple: how could I consistently get better results and higher-quality responses from the AI models I use, while also reducing the time it takes to arrive at a solid outcome?&lt;/p&gt;

&lt;p&gt;Previously, my workflow leaned more toward Vibe Coding Prompting, or VCP. My usual approach was to build things first, then ask the AI to review what I might have overlooked, especially around caching strategy and SQL performance.&lt;/p&gt;

&lt;p&gt;The problem, however, was that VCP often gave me responses that did not meet the standard I was aiming for. Hallucinations were quite common, and the issue became even more obvious when the context grew longer and more complex.&lt;br&gt;
Because of that, I changed the way I use AI in my daily workflow. I moved from VCP toward SDD, or Spec-Driven Development. From my experience so far, SDD gives me significantly better responses than VCP.&lt;/p&gt;




&lt;p&gt;That said, I have not abandoned VCP entirely. It is still useful when I want the AI agent to handle repetitive tasks for me, so I can stay focused on work that requires more attention and deeper thinking.&lt;/p&gt;

&lt;p&gt;The first time I used SDD, I stuck with it almost immediately because it felt like working with a highly capable Project Manager. That said, SDD does take more time at the beginning. You need clear stakeholder requirements first. Then you need the AI to align properly with the spec before execution begins. This is different from VCP, where you can often jump straight into getting an output. The trade-off is that the output may not be as strong or as reliable as what SDD produces.&lt;/p&gt;

&lt;p&gt;The slower start is normal. That has always been true in software development. Even before AI became part of our workflow, we still needed time to analyze requirements and think things through properly. The difference is that, over the long run, SDD has accelerated my workflow by more than 30%. The quality of the output is better, and the number of bugs is lower. As a result, I spend far less time debugging.&lt;/p&gt;




&lt;p&gt;At the moment, this is how I work with AI. You may want to adopt parts of this workflow, or perhaps share your own with me. I am always open to learning from how others approach their process. For now, this is the workflow that works best for me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I manually initialize all Laravel, Symfony, Nuxt, Next, or Express projects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I set up the initial routes that I know the project will need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I create the necessary SKILLS to ensure my AI agent can follow SDD, read related specs correctly, and understand my preferred code patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once those first three steps are in place, I create a &lt;code&gt;specs/&lt;/code&gt; folder, along with the relevant subfolders for the specs I want the AI to work on. For example, I recently needed a shell script for a data pipeline process, so I created &lt;code&gt;specs/shell/&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Before asking the AI to generate the basic files for SDD, I write the &lt;code&gt;readme.md&lt;/code&gt; for that spec myself. This document contains the full stakeholder requirements, including the WHY behind the spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I then run a prompt that instructs the AI to read and analyze that &lt;code&gt;readme.md&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Based on its analysis, I ask the AI to raise any questions it may have before completing the development plan for that spec.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once I answer those questions and it generates the development plan, I review that plan carefully, step by step. If anything feels off, I correct it manually until I am fully satisfied, and only then do I ask the AI to execute the plan.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am not claiming that this is the best workflow. It is simply the workflow that fits the way I work today. I still think critically, and I still write code manually. What SDD gives me is a more structured path, fewer bugs, and a faster development cycle overall. That also allows me to spend more time on the things that matter most, such as design patterns, architecture, and other higher-level engineering decisions.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Beyond CRUD: The Developer’s Ascent – A Story of Growth</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sun, 23 Nov 2025 04:17:00 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/beyond-crud-the-developers-ascent-a-story-of-growth-486c</link>
      <guid>https://dev.to/msulaimanmisri/beyond-crud-the-developers-ascent-a-story-of-growth-486c</guid>
      <description>&lt;p&gt;Based on my personal experience. But blend with a Journalist-like story to make it more interesting.&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%2Fiwb4rec71xhwl4ojqc15.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%2Fiwb4rec71xhwl4ojqc15.png" alt="Author-codes-in-the-room" width="800" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kuala Lumpur — It’s a scene familiar to many in the tech world: a young developer, lit by the glow of a laptop screen, celebrates the launch of their first simple web application. But for seasoned software engineer Ahmad (not his real name), that moment was just the first step of a decade-long journey climbing from novice coder to technical architect—a journey marked less by the mastery of CRUD (Create, Read, Update, Delete) and more by a relentless pursuit of growth and complexity.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;“I still remember the first time my own app let someone add and delete a note,” Ahmad recalls. “It felt like magic. CRUD opened the gate to programming for me. But I eventually realized it’s really just basic survival.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;For years, CRUD skills sufficed. Ahmad bounced between languages—PHP, JavaScript, Go—building countless forms and tables, spinning up databases, and deploying apps that managed users and lists. The early victories, however, gave way to a sense of monotony. “It’s easy to fall into the loop,” he says. “Every project starts to look the same. You wonder, is this all I’m going to do?”&lt;/p&gt;




&lt;p&gt;Industry veterans say that realization marks an important inflection point—the plateau that separates junior developers from their more senior peers. “Moving past CRUD is not about abandoning the basics,” says Maya, Ahmad’s former mentor and team lead. “It’s about asking bigger questions: How does this system work for the business? What happens if traffic doubles? If a bug wipes out the database, are we ready?”&lt;/p&gt;




&lt;p&gt;For Ahmad, the turning point came when his team was tasked with integrating real-time payments and automated reporting into their platform. CRUD apps, he discovered, could not answer questions about reliability, scalability, error recovery, or business impact. “Suddenly, I had to think like an architect, not a form designer,” he tells us. “From database indexing to API reliability, every decision mattered.”&lt;/p&gt;




&lt;p&gt;The role of a Senior Developer, Ahmad explains, is less about coding individual features and more about designing systems and processes. He describes late nights debugging production issues, painstaking data modeling, and the challenge of translating technical risks to cross-department stakeholders. “You don’t just write the code. You explain why, negotiate trade-offs, and make sure the solution actually solves a real-world problem.”&lt;/p&gt;




&lt;p&gt;Beyond the technical, communication skills emerge as critical. “The bigger the system, the more people involved,” Ahmad notes. “You need to speak business, not just code. Convincing marketing or ops to invest in better logging or infrastructure—that's what really moves projects forward.”&lt;/p&gt;




&lt;p&gt;This ethos of perpetual learning runs deep. Technologies like Laravel Collections, he says, seem straightforward—until new custom methods reinvent familiar workflows. Ahmad regularly returns to old documentation, finding surprises in the details. “Even when it’s a repeat topic, there’s always something new,” he reflects. “The best engineers constantly re-learn and re-invest in their fundamentals.”&lt;/p&gt;




&lt;p&gt;Experts echo this view. “In the real world, seniors spend as much time mentoring, designing, and testing as they do coding,” Maya explains. “The real ascent is about growing as a leader and problem-solver, not just a programmer.”&lt;/p&gt;




&lt;p&gt;Today, Ahmad mentors teams across departments, reviews code, drafts architectural diagrams, and steers projects from conception to completion. “I see junior devs excited about CRUD. I tell them it’s a great start. But don’t stop there—your road is far longer and richer.”&lt;/p&gt;




&lt;p&gt;As the tech world races forward, Ahmad’s story serves as both blueprint and inspiration—a testament to the climb from CRUD to creativity, from novice to senior, and from solitary coder to collaborative leader.&lt;/p&gt;




&lt;p&gt;“CRUD is the start of the story,” Ahmad concludes, “but the most exciting chapters come after.”&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>programming</category>
      <category>careerdevelopment</category>
    </item>
    <item>
      <title>Understanding Polymorphism vs. Polymorphic in Programming</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Fri, 07 Feb 2025 07:04:12 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/understanding-polymorphism-vs-polymorphic-in-programming-471n</link>
      <guid>https://dev.to/msulaimanmisri/understanding-polymorphism-vs-polymorphic-in-programming-471n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you've ever dived into Object-Oriented Programming (OOP) or worked with an ORM like Laravel's Eloquent, you've likely come across the terms &lt;code&gt;Polymorphism&lt;/code&gt; and &lt;code&gt;Polymorphic Relationship&lt;/code&gt; (will use Polymorphic after this). While they sound similar, they refer to two distinct concepts.&lt;/p&gt;

&lt;p&gt;Many developers, especially those new to these concepts, often confuse them. In this post, I'll break down what each term means, how they are used, and &lt;strong&gt;why understanding the difference is crucial for writing clean and efficient code.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Polymorphism?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Polymorphism&lt;/code&gt; is a fundamental concept in Object-Oriented Programming (OOP) that allows objects of different classes to be treated as objects of a common superclass. It enables a single interface to be used with different underlying data types, improving code reusability and flexibility.&lt;/p&gt;

&lt;p&gt;There are two primary types of polymorphism. &lt;code&gt;Method Overriding&lt;/code&gt; and &lt;code&gt;Method Overloading&lt;/code&gt;. For the sake of the PHP and this sharing, we focus on the first type only.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example of Polymorphism in PHP (Method Overriding)
&lt;/h3&gt;

&lt;p&gt;Let's take a real-world example. Assume we have a User system where different types of users (Admin, Customer) have different access levels.&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="cd"&gt;/**
* Main (or Parents) Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&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;getRole&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="s2"&gt;"General User"&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="cd"&gt;/**
* Child Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&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;getRole&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="s2"&gt;"Administrator - Full Access"&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="cd"&gt;/**
* Child Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;User&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;getRole&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="s2"&gt;"Customer - Limited Access"&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="cd"&gt;/**
* Instantiate the Class - Object
*/&lt;/span&gt;
&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="o"&gt;=&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;Admin&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;Customer&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;User&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;$users&lt;/span&gt; &lt;span class="k"&gt;as&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;echo&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;getRole&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="kc"&gt;PHP_EOL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Administrator&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Full&lt;/span&gt; &lt;span class="nc"&gt;Access&lt;/span&gt;
&lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Limited&lt;/span&gt; &lt;span class="nc"&gt;Access&lt;/span&gt;
&lt;span class="nc"&gt;General&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, even though we are calling &lt;code&gt;getRole()&lt;/code&gt; on different objects, they return different results based on their respective class implementations. &lt;strong&gt;This is the power of polymorphism&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ok now, I hope you understand about &lt;code&gt;polymorphism&lt;/code&gt;. Let's go to other terms, &lt;code&gt;polymorphic&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Polymorphic?
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;Polymorphic&lt;/code&gt; is a database design pattern used in Object-Relational Mapping (ORM) systems like Laravel's Eloquent. It allows a single model to be associated with multiple other models without needing multiple foreign keys.&lt;/p&gt;

&lt;p&gt;For example, let's say we have an &lt;code&gt;Image&lt;/code&gt; model that can be associated with both a &lt;code&gt;Post&lt;/code&gt; and a &lt;code&gt;User&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Instead of creating separate &lt;code&gt;post_id&lt;/code&gt; and &lt;code&gt;user_id&lt;/code&gt; columns in the images table, we use a polymorphic relationship with imageable_id and imageable_type columns.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Example of Polymorphic Relationship in Laravel
&lt;/h3&gt;

&lt;p&gt;In your migration file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&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;id&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;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'url'&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;morphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'imageable'&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;timestamps&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;In your Model :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
* Image Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;imageable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;morphTo&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="cd"&gt;/**
* Post Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;morphMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Image&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;'imageable'&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="cd"&gt;/**
* User Class
*/&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;morphMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Image&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;'imageable'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this codes, you can do like this when Data Creation :&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;$post&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$post&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;images&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="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'post_image.jpg'&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;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;images&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="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'profile_picture.jpg'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, both &lt;code&gt;Post&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; models can have associated &lt;code&gt;images&lt;/code&gt; without needing separate foreign keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  Polymorphic Relationships Exist Beyond Laravel
&lt;/h2&gt;

&lt;p&gt;Although Laravel has made Polymorphic relationships popular in the PHP ecosystem, this concept exists in other frameworks and ORMs such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Django (Python) – Uses Generic Foreign Key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hibernate (Java) – Uses Single Table Inheritance or Join Table Inheritance&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Both &lt;code&gt;Polymorphism&lt;/code&gt; and &lt;code&gt;Polymorphic&lt;/code&gt; are crucial concepts, but they serve different purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Polymorphism&lt;/code&gt; is an OOP concept that allows multiple classes to share the same interface and behave differently based on their implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Polymorphic&lt;/code&gt; usually referred as &lt;code&gt;Polymorphic Relationship&lt;/code&gt; are a database ORM feature that allows a single model to relate to multiple other models dynamically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  To visualize the difference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Polymorphism&lt;/code&gt; is like having different types of users (Admin, Customer, Guest) who inherit from a common &lt;code&gt;User&lt;/code&gt; class but override methods to behave differently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Polymorphic&lt;/code&gt; are like an &lt;code&gt;Image&lt;/code&gt; table where a single image can belong to either a Post, a User, or even a Product, without needing multiple foreign keys.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;&lt;u&gt;Understanding the difference between these two concepts helps you write cleaner, more maintainable, and scalable code&lt;/u&gt;&lt;/strong&gt;. Whether you’re designing an object-oriented system or a database schema, knowing when and how to use polymorphism can make a huge difference in your project's architecture.&lt;/p&gt;

&lt;p&gt;Even there's some Cons. But I don't want to explain it here. Now, it's your job to find the Cons ;)&lt;/p&gt;

&lt;p&gt;I'm sure you have implemented the &lt;code&gt;polymorphism&lt;/code&gt; in your Laravel project. But Have you used polymorphic relationships in your projects? Let me know in the comments below! 🚀&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>oop</category>
      <category>database</category>
    </item>
    <item>
      <title>Understanding Laravel Queues: queue:work vs queue:listen and Why queue:restart Matters</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sat, 01 Feb 2025 13:51:09 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/understanding-laravel-queues-queuework-vs-queuelisten-and-why-queuerestart-matters-33cc</link>
      <guid>https://dev.to/msulaimanmisri/understanding-laravel-queues-queuework-vs-queuelisten-and-why-queuerestart-matters-33cc</guid>
      <description>&lt;p&gt;Recently, I released a Laravel package called &lt;a href="https://github.com/msulaimanmisri/easy-deploy" rel="noopener noreferrer"&gt;EasyDeploy&lt;/a&gt;, and someone asked me why I included &lt;code&gt;php artisan queue:restart&lt;/code&gt; instead of just using &lt;code&gt;php artisan queue:work&lt;/code&gt; or &lt;code&gt;php artisan queue:listen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This question made me realize that many developers aren't fully aware of how Laravel's queue system works, especially when using Supervisor. So in this post, let's break it down step by step.&lt;/p&gt;

&lt;p&gt;By the way, I will shorten the command to like &lt;code&gt;queue:work&lt;/code&gt;. I hope you can understand that it's mean &lt;code&gt;php artisan queue:work&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 &lt;code&gt;queue:work&lt;/code&gt; vs &lt;code&gt;queue:listen&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before we talk about queue:restart, let's first understand the difference between &lt;code&gt;queue:work&lt;/code&gt; and &lt;code&gt;queue:listen&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠 php artisan queue:work
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Runs a queue worker once and then exits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since Laravel now runs &lt;code&gt;queue:work&lt;/code&gt; in daemon mode by default, you can simply use:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Because of &lt;code&gt;queue:work&lt;/code&gt; runs in daemon mode by default, the worker stays running without restarting Laravel for every job, making it &lt;strong&gt;faster&lt;/strong&gt; and &lt;strong&gt;more efficient for production&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🎧 php artisan queue:listen
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Listens for new jobs continuously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restarts Laravel for every job, which ensures fresh code &lt;strong&gt;but makes it slower than queue:work&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Good for development, but &lt;strong&gt;not recommended for production&lt;/strong&gt; due to performance overhead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Which One to Use?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;queue:work&lt;/code&gt; in production for better performance since it already runs in daemon mode by default.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;queue:listen&lt;/code&gt; in development when you want changes to be reflected immediately without restarting the worker.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Why queue:restart Is Necessary
&lt;/h2&gt;

&lt;p&gt;Now that we understand the difference, let's talk about &lt;code&gt;queue:restart&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if you're using &lt;code&gt;queue:work&lt;/code&gt;, the worker keeps running indefinitely. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you deploy new code, the worker still runs old code because it never restarted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you update a model, job, or database structure, the queue worker won’t pick up the changes. Because the worker does not automatically reload the application state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve this, Laravel provides:&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 queue:restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command signals all workers to gracefully exit after finishing their current job, allowing them to be restarted and reload the updated code.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 How Supervisor Fits In
&lt;/h2&gt;

&lt;p&gt;Many Laravel developers use &lt;a href="https://supervisord.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;Supervisor&lt;/strong&gt;&lt;/a&gt; to keep queue workers running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supervisor auto-restarts workers if they crash, ensuring that queue jobs are always processed.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, &lt;strong&gt;Supervisor does not restart workers when you deploy new code.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is why &lt;code&gt;queue:restart&lt;/code&gt; is important: it tells existing workers to stop so that Supervisor can restart them with the latest code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 Without &lt;code&gt;queue:restart&lt;/code&gt;, your queue workers might continue using old code after deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Best Practices for Laravel Queues in Production
&lt;/h2&gt;

&lt;p&gt;When deploying updates, always do:&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 migrate --force
php artisan queue:restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that:&lt;/p&gt;

&lt;p&gt;✅ Database migrations apply correctly.&lt;/p&gt;

&lt;p&gt;✅ Queue workers reload the latest code.&lt;/p&gt;

&lt;p&gt;✅ No jobs get stuck due to outdated logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This command is included in my package. I'm using this for years&lt;/strong&gt;&lt;/p&gt;




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

&lt;p&gt;Understanding how Laravel queues work is crucial for building reliable and scalable applications. If you're using Supervisor, make sure to include &lt;code&gt;queue:restart&lt;/code&gt; in your deployment workflow to prevent workers from running outdated code.&lt;/p&gt;

&lt;p&gt;I hope this post clarifies the difference between &lt;code&gt;queue:work&lt;/code&gt;, &lt;code&gt;queue:listen&lt;/code&gt;, and why &lt;code&gt;queue:restart&lt;/code&gt; is necessary.&lt;/p&gt;

&lt;p&gt;If you're interested in automating your Laravel deployments, check out &lt;a href="https://github.com/msulaimanmisri/easy-deploy" rel="noopener noreferrer"&gt;EasyDeploy&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Have any questions? Let's discuss in the comments! 🚀&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>supervisor</category>
      <category>php</category>
      <category>queue</category>
    </item>
    <item>
      <title>My Journey from BootstrapCSS to TailwindCSS: A Backend Developer’s Perspective</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Thu, 03 Oct 2024 01:44:59 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/my-journey-from-bootstrapcss-to-tailwindcss-a-backend-developers-perspective-2n1c</link>
      <guid>https://dev.to/msulaimanmisri/my-journey-from-bootstrapcss-to-tailwindcss-a-backend-developers-perspective-2n1c</guid>
      <description>&lt;p&gt;As a backend developer, my journey in the world of web development has been filled with learning and adapting to new technologies. Recently, I made the switch from BootstrapCSS (Bootstrap) to TailwindCSS (Tailwind), and I’d like to share my experience along with a comparison of both frameworks.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering Tailwind: From Skepticism to Adoption
&lt;/h2&gt;

&lt;p&gt;I first came across Tailwind through the front-end community. I’ve been following Adam Wathan, the founder of Tailwind, since he published his course about Laravel. However, at the time, I was more into Bootstrap because, as a backend developer, front-end styling wasn’t my priority.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
But as time went on, I had to evolve into a Full Stack Developer. When working with frameworks like Laravel and WordPress, companies expect you to handle both backend and frontend. This shift pushed me to rethink my approach to front-end development, and eventually, my frustrations with Bootstrap led me to explore Tailwind.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
Before Tailwind, I even tried Bulma, but the community wasn't as active or supportive compared to Tailwind and Bootstrap.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
What made Tailwind even more appealing was how I could avoid writing separate CSS files. With Tailwind’s utility-first approach, I could apply styles directly within the Blade or PHP files, similar to inline styling but with more power and time efficiency. It saved me the hassle of going back and forth between CSS and HTML, making development much smoother.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance and Flexibility: Why Tailwind Wins for Me
&lt;/h2&gt;

&lt;p&gt;When it comes to performance, Tailwind edges out Bootstrap, especially with its JIT (Just-in-Time) compilation and tree-shaking mechanism. With Bootstrap, you often end up loading a ton of unused CSS classes, which can bloat the file size. Tailwind, on the other hand, compiles only the classes I use. This results in a leaner, more efficient CSS file, directly improving page load times and overall performance.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
As for flexibility, Tailwind offers way more freedom than Bootstrap. In Bootstrap, while there’s customization available through SCSS or LESS, it often feels like an extra step. Tailwind, however, gives you customization directly through utility classes. Need a specific width? No problem—use w-[200px] or w-[50em]. Want a custom background with transparency? bg-pink-500/20 gets the job done.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
This design freedom makes Tailwind powerful, allowing me to create exactly what I envision without writing custom CSS files or relying on pre-designed components.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;/p&gt;

&lt;h2&gt;
  
  
  Adjusting to Tailwind: A Learning Curve
&lt;/h2&gt;

&lt;p&gt;One of the key reasons my development slowed down when switching to Tailwind was the shift in approach. With Bootstrap, a lot of the heavy lifting is done for you. Bootstrap comes packed with pre-built components like btn, nav, container, and more. It’s quick and easy to implement, often requiring just a few classes to achieve a fully functional and styled element.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
On the other hand, Tailwind takes a more utility-first approach. Instead of pre-built components, you’re in control of each aspect of the design. For example, creating a simple button in Bootstrap is as quick as writing btn btn-primary. In Tailwind, you need to manually define each property like rounded-md p-4 text-white bg-blue-500 hover:bg-blue-300. This gives you more design flexibility but also increases the amount of code you write.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
This learning curve and extra level of detail in styling make Tailwind slower at first. You’re responsible for crafting each component from scratch, which takes more time compared to using Bootstrap’s ready-to-use components. However, once you get the hang of Tailwind, the payoff in terms of performance, customization, and design freedom becomes clear.&lt;br&gt;
⁣&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and Lessons Learned: Transitioning to Tailwind
&lt;/h2&gt;

&lt;p&gt;Switching to Tailwind wasn’t without its challenges. As someone who initially focused on backend development, adjusting to a utility-first CSS framework like Tailwind required a shift in mindset. Unlike Bootstrap, which offers pre-built components and a structured approach to UI design, Tailwind forces you to build everything from the ground up.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
The challenge was in balancing flexibility with the learning curve. Initially, it felt like I was spending more time manually writing classes for every design element, which slowed down my development process. There was also a period where I struggled to remember Tailwind’s utility classes, making it harder to develop quickly compared to Bootstrap’s familiar component classes.&lt;br&gt;
⁣&lt;/p&gt;

&lt;p&gt;However, the key lesson I learned was patience. Once I got over the initial learning curve, Tailwind became second nature. I realized that while the upfront effort is higher, the long-term gains in flexibility and performance were worth it. The framework’s approach to responsive design, customization, and optimization pays off in larger projects, especially when performance is critical.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
Advice for Developers Transitioning to Tailwind&lt;br&gt;
For front-end developers, Tailwind will feel like home. The utility-first approach gives you granular control over every aspect of the design, allowing you to build responsive and high-performance websites with ease. If you enjoy customizing layouts and fine-tuning the look of your site, Tailwind is perfect for you.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
For back-end developers, my advice is to start with Bootstrap. Learn and get comfortable with CSS concepts first. Bootstrap’s structured component system will help you ease into front-end development. Once you’re comfortable with the basics of CSS, consider moving to Tailwind to unlock its full potential for performance and design flexibility.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
If you want to go faster, consider asking your designer to create the mockups first. This way, you’ll have a clear visual guide on how to bring your designs to life using Tailwind.&lt;br&gt;
⁣&lt;br&gt;
⁣&lt;br&gt;
In modern website design, performance is just as important as UI. Don’t overlook this aspect. Tailwind’s JIT compilation and efficient CSS bundle make it a great option for developers who prioritize speed and user experience. It’s important to balance aesthetics with functionality, ensuring that your websites not only look good but perform well too.&lt;br&gt;
⁣&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>bootstrap</category>
      <category>frontend</category>
      <category>backend</category>
    </item>
    <item>
      <title>Embracing Agile, Scrum, and Kanban in Project Management: A Personal Journey</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Mon, 30 Sep 2024 12:51:32 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/embracing-agile-scrum-and-kanban-in-project-management-a-personal-journey-54jn</link>
      <guid>https://dev.to/msulaimanmisri/embracing-agile-scrum-and-kanban-in-project-management-a-personal-journey-54jn</guid>
      <description>&lt;p&gt;Managing projects in a software house can be both rewarding and challenging. One of the biggest challenges I faced was shifting from the traditional Waterfall model to a more flexible approach using Agile, Scrum, and Kanban. My team and I were tasked with building a social media platform for book lovers—a project that required close collaboration, timely iterations, and a clear workflow. This is a reflection of how we managed the process, the obstacles we faced, and the lessons learned.&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%2Ffq5nz8s2elim57dajgc7.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%2Ffq5nz8s2elim57dajgc7.png" alt="My Team" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Waterfall Challenge
&lt;/h2&gt;

&lt;p&gt;Before this project, we had always used the Waterfall methodology. In a software house, this felt like the natural choice. Waterfall gives you that sense of control, where every stage of the project is neatly planned and executed in sequence: requirements, design, development, and testing. But this approach often led to rigid timelines and miscommunication. If a change was needed during development, going back to earlier stages was cumbersome, resulting in delays and frustrations.&lt;/p&gt;

&lt;p&gt;For this project, we realized that the Waterfall approach wouldn't allow us to be flexible enough to meet evolving requirements, especially for a dynamic platform like a social media network. This realization led us to embrace Agile, combining Scrum and Kanban to create a hybrid approach tailored to our needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shift to Agile-Scrum-Kanban: A New Way of Thinking
&lt;/h2&gt;

&lt;p&gt;Transitioning to Agile wasn't as smooth as we initially hoped. Although we had the right tools—Scrum for organizing sprints and Kanban for managing tasks—the team struggled with one significant challenge: shaking off the habits formed from years of Waterfall projects. Developers found themselves waiting for the design to be finalized before starting, and the workflow often felt like we were reverting to the Waterfall model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adapting to Challenges
&lt;/h2&gt;

&lt;p&gt;While we haven’t fully found the perfect solution, one of the approaches we are considering is to embrace cross-functional teams. Having designers, developers, and even stakeholders work together from the very start of the sprint could help reduce delays caused by waiting on one another. In our current approach, we had scenarios where the back-end developer would start working on the business logic, the designer would begin creating high-fidelity designs in Figma based on wireframes, and the front-end developer would start creating the front-end skeleton.&lt;/p&gt;

&lt;p&gt;Although it felt like we were following an Agile approach, this setup often mirrored the Waterfall process, where one team member had to wait for another to complete their work. For example, the front-end developer would wait for the final design to be implemented, resulting in unnecessary delays. This sequential dependency made it challenging to move at the speed of Agile promises.&lt;/p&gt;

&lt;p&gt;To counter this, we’re working towards more parallel processing within sprints. Breaking tasks into smaller, independent chunks that don’t rely on sequential completion would allow developers and designers to work simultaneously. This shift would significantly reduce bottlenecks and make our sprints smoother.&lt;/p&gt;

&lt;p&gt;Additionally, we’ve started focusing on more robust sprint reviews and retrospectives to highlight these bottlenecks in real-time, enabling us to quickly adapt and evolve our workflow. In the future, shorter iterations and more real-time feedback are essential to prevent falling back into Waterfall-like habits.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Outcome: A Successful Sprint
&lt;/h2&gt;

&lt;p&gt;Despite the challenges, the outcome of the project was extremely positive. By using the Agile-Scrum-Kanban mix, we were able to build the necessary features without any major conflicts during the sprints. The key to this success was the clear communication and alignment we had during the backlog discussions. Everyone knew exactly what needed to be done and what the priorities were, allowing us to complete each sprint without confusion or scope creep.&lt;/p&gt;

&lt;p&gt;The platform for book lovers came together smoothly, with each function being developed and tested in clear iterations. We were able to deliver value consistently, meeting the expectations of both the stakeholders and the end-users.&lt;/p&gt;

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

&lt;p&gt;Switching from Waterfall to a hybrid Agile approach wasn’t easy, but it was a necessary step for us to evolve as a team. While we’re still fine-tuning our process, the Agile-Scrum-Kanban framework has proven to be more flexible and efficient for our projects. If you’re considering making the switch, my advice is to involve your whole team from the start, allow for flexibility, and don’t be afraid to iterate on your process just like you do on your product.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>scrum</category>
      <category>agile</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Story From WordPress to Leadership: A Software Engineer's Journey</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sat, 20 Jul 2024 14:24:03 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/a-story-from-wordpress-to-leadership-a-software-engineers-journey-h3</link>
      <guid>https://dev.to/msulaimanmisri/a-story-from-wordpress-to-leadership-a-software-engineers-journey-h3</guid>
      <description>&lt;p&gt;In the dynamic world of software development, career paths often take unexpected turns. This is the story of a passionate programmer whose journey led him from specialized web development to a leadership role, and ultimately back to his coding roots—albeit in a different company and with newfound wisdom.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Early Days: Mastering WordPress
&lt;/h2&gt;

&lt;p&gt;Our story begins with a dedicated WordPress developer, crafting digital experiences with a blend of creativity and technical skill. Each day brought new challenges in theme development, plugin customization, and creating responsive designs. The world of content management systems was his playground, and he excelled in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broadening Horizons: The Software Engineer.
&lt;/h2&gt;

&lt;p&gt;Recognizing his potential, the company soon promoted him to the role of Software Engineer. This transition marked a significant step in his career, broadening his horizons beyond WordPress to tackle a diverse array of general software development tasks.&lt;/p&gt;

&lt;p&gt;The excitement of exploring different technologies and solving varied challenges fueled his passion for coding. From backend systems to front-end frameworks, our protagonist immersed himself in the vast ocean of software development, continuously learning and growing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Unexpected Promotion: Lead Developer
&lt;/h2&gt;

&lt;p&gt;Just as he was hitting his stride in this new role, another opportunity presented itself. The company offered him a promotion to Lead Developer—a position that promised not only a substantial salary increase but also the chance to shape the direction of projects and mentor junior team members.&lt;/p&gt;

&lt;p&gt;Initially hesitant, our developer was swayed by the company's predicament. There was no one else to fill the crucial role of overseeing developer workflows and managing projects. With a mix of trepidation and a sense of duty, he accepted the position, believing he could balance his passion for programming with his new responsibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality of Leadership
&lt;/h2&gt;

&lt;p&gt;What followed was a stark awakening to the realities of leadership in the tech industry. The once-comfortable world of coding gave way to a landscape dominated by meetings, stakeholder management, and business strategy. Our lead developer found himself spending a mere 20% of his time on actual coding—and even that was primarily for research purposes rather than project work.&lt;/p&gt;

&lt;p&gt;The daily routine became a source of emotional turmoil. Sitting with his team, listening to discussions about cutting-edge technologies and the rhythmic clicking of keyboards, stirred a profound sense of longing. Each line of code typed by his team members felt like a reminder of the path he had reluctantly left behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Struggle for Balance
&lt;/h2&gt;

&lt;p&gt;Concerned about his growing dissatisfaction, our protagonist approached senior management, hoping for a solution. However, the response was disheartening. The company lacked qualified internal candidates to take over the lead developer role, leaving him firmly entrenched in his new position.&lt;/p&gt;

&lt;p&gt;As the months turned into years, our lead developer gained valuable insights into the business side of software development. He broadened his perspective and acquired new skills. Yet, these professional gains came at a significant personal cost. The joy he once found in programming had dimmed, replaced by the constant pressure of managerial responsibilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision to Move On
&lt;/h2&gt;

&lt;p&gt;After two years in the lead developer role, our protagonist realized that his true passion lay in hands-on coding. The experience had been invaluable, providing insights into project management, team dynamics, and business operations. However, it had also made clear that his career goals were firmly rooted in technical excellence rather than people management.&lt;/p&gt;

&lt;p&gt;With a heavy heart but a clear vision for his future, he decided it was time to move on. He was grateful for the trust the company had placed in him and the opportunities they had provided. Their support played a crucial role in his professional growth, offering lessons and experiences that would continue to influence his career.&lt;/p&gt;

&lt;h2&gt;
  
  
  A New Chapter: Return to Coding
&lt;/h2&gt;

&lt;p&gt;Armed with a wealth of experience and a renewed sense of purpose, our protagonist embarked on a job search. He faced challenges along the way, discovering that his extended time away from hands-on coding had dulled some of his technical skills. Several companies were hesitant to hire an external lead developer, preferring to promote from within.&lt;/p&gt;

&lt;p&gt;However, persistence paid off. He found a new role as a Senior Full-Stack Engineer at a different company. In this position, he made it clear from the outset that he wanted to focus on technical work, avoiding management responsibilities except for mentoring junior developers through code reviews.&lt;/p&gt;

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

&lt;p&gt;This journey, though challenging, yielded valuable insights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Leadership roles, while prestigious, demand a genuine interest in management and business strategy. It's crucial to align career moves with personal passions and long-term goals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The title and compensation of a lead developer may be alluring, but they come with significant responsibilities that can fundamentally alter one's day-to-day work and career trajectory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintaining technical skills is crucial, even in management roles, to keep career options open.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's essential to regularly reassess career goals and have the courage to make changes when necessary.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Today, our protagonist has found his way back to his true calling. As a Senior Full-Stack Engineer in his new company, he's rediscovered the joy of solving complex technical problems and staying at the forefront of software development.&lt;/p&gt;

&lt;p&gt;His experience serves as a poignant reminder of the importance of self-awareness in career planning. It underscores the value of aligning professional roles with personal passions and the courage to course-correct when necessary.&lt;/p&gt;

&lt;p&gt;For those standing at similar career crossroads, remember: the most fulfilling path is often the one that resonates with your core interests and allows you to leverage your strongest skills. In the dynamic world of software development, there's always room for growth—but it should be growth on your own terms.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>softwareengineering</category>
      <category>management</category>
    </item>
    <item>
      <title>Create a re-useable Mailing Code in Laravel</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sat, 06 Apr 2024 17:54:28 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/create-a-re-useable-mailing-code-in-laravel-3bd4</link>
      <guid>https://dev.to/msulaimanmisri/create-a-re-useable-mailing-code-in-laravel-3bd4</guid>
      <description>&lt;p&gt;Hi there! In today's posting, I would like to share with you guys how to create a &lt;code&gt;Laravel Mailing&lt;/code&gt; reusable code.&lt;/p&gt;

&lt;p&gt;What I mean here is not the &lt;code&gt;php artisan make:mail&lt;/code&gt;. But the &lt;code&gt;Mail::to&lt;/code&gt; Syntax.&lt;/p&gt;

&lt;p&gt;I'm building one mechanism in my application to send the reminder email to all of our targeted users. There are two ways to send to them. One is done manually (by clicking a button and then sending the email), second is done automatically (by using Laravel Scheduler)&lt;/p&gt;

&lt;p&gt;The problem I faced was a lot of &lt;code&gt;Mail::to&lt;/code&gt; syntax logic that I needed to code. The full code is like this,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mail::to($user-&amp;gt;email)
-&amp;gt;send(new SendFirstReminder($user-&amp;gt;name, $user-&amp;gt;email));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It took me nearly 20 seconds to code it (I'm a slow typer)!&lt;/p&gt;

&lt;p&gt;And there are a few places where I need to put the code. Such as Controller, and Console.&lt;/p&gt;

&lt;p&gt;That's when I started to think. &lt;code&gt;what if I need to use that mail code again&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;So I need to spend another 20 seconds again? Of course, I don't want to do that again.&lt;/p&gt;

&lt;p&gt;So what happened is, that I created a custom &lt;code&gt;Services Class&lt;/code&gt;. I named it as &lt;code&gt;EmailReminder&lt;/code&gt;. In this class where I gather all the reminder emails. Everything is in one place.&lt;/p&gt;

&lt;p&gt;Then I use the &lt;code&gt;static method&lt;/code&gt; to make it more readable.&lt;/p&gt;

&lt;p&gt;As you can see in this image, after I created the &lt;code&gt;EmailReminder&lt;/code&gt; services, I can call it wherever I want without spending 20 seconds to code it. It can be reused in all places.&lt;/p&gt;

&lt;p&gt;I just need to call it statically and then it will work like usual. But it is shortened and more readable (at least from my point of view)&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%2Fqgqo130j08g0eoqwxjtk.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%2Fqgqo130j08g0eoqwxjtk.png" alt="sulaiman-mail-code" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later I will create another post on how I created a reusable Local Scope logic for my application.&lt;/p&gt;

&lt;p&gt;If you have other suggestions, comment below. I'd love to hear about your code strategy.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>Inverse of hasManyThrough Laravel</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Wed, 01 Feb 2023 07:26:38 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/inverse-of-hasmanythrough-laravel-48ed</link>
      <guid>https://dev.to/msulaimanmisri/inverse-of-hasmanythrough-laravel-48ed</guid>
      <description>&lt;p&gt;Currently, I'm developing a Learning Management System called &lt;a href="https://kelasdesign.my/" rel="noopener noreferrer"&gt;Kelas Design&lt;/a&gt;. And today my task is to count how many Episodes do the Series have and vice-versa.&lt;/p&gt;

&lt;p&gt;So I do the logic using Laravel Built-in Eloquent : Has Many Though. What's my logic look like is :&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%2F3y9yo8batmlvkgeq33zm.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%2F3y9yo8batmlvkgeq33zm.png" alt="Image description" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I will get the Episodes data through Section. That's fine. But how about getting the Episode and which Series it's belongs to?&lt;/p&gt;

&lt;p&gt;I realized that, in Laravel documentation, there's no instruction about Inverse of Has Many Through or Has One Through.&lt;/p&gt;

&lt;p&gt;And since they don't provide that instruction, so I do need to create it manually. Usually if I faced a situation like this, I always reverse engineer the logic.&lt;/p&gt;

&lt;p&gt;For example, Laravel has the built-in function such as Has Many Through &amp;amp; Has One Through.&lt;/p&gt;

&lt;p&gt;So what I do is in Episode Model, I create method and returning Has One Through.  If you're thinking about using belongsTo, you are wrong.&lt;/p&gt;

&lt;p&gt;And this is my logic :&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%2Fubip6zeqe8yj8ibh3fq4.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%2Fubip6zeqe8yj8ibh3fq4.png" alt="Image description" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, you can just passed two (2) arguements if you are following Laravel convention. But in my case, If you just passed the two arguements, it will print an Error. Which the system cannot find the column you wanted.&lt;/p&gt;

&lt;p&gt;With the extra arguements, you can search more depth. The third arguement is called &lt;code&gt;$first_key&lt;/code&gt; and the fourth is &lt;code&gt;$second_key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Adding this, will allow the system to search more deep in your Database. And Eventually, will return you a data that you need. The third and fourth arguements is not nessasary an 'id'. It can be something else.&lt;/p&gt;

&lt;p&gt;That's all, I hope my solution also can solve your situation like me also. If you have a better approach to do the inverse, please do comment below :)&lt;/p&gt;

&lt;p&gt;PS : I've stumble upon one package name &lt;code&gt;staudenmeir/belongs-to-through&lt;/code&gt;. Tested it and based on what I read at the files, this package also will solve my problem. However, I do not seek something overkill like this. Look at my solution, compared to this package. Even though the syntax is much cleaner, but I still need to download the package that have many files. And that I do not want to.&lt;/p&gt;

&lt;p&gt;By the time I wrote this blog, this package has issue. Please refer to &lt;a href="https://github.com/staudenmeir/belongs-to-through/issues/75" rel="noopener noreferrer"&gt;Github Issue&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>[BM] Bagaimana untuk menikmati kenaikkan gaji bagi seorang Web Developer</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Sun, 22 Jan 2023 06:03:57 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/bm-tips-untuk-naik-gaji-bagi-seorang-web-developer-3ob1</link>
      <guid>https://dev.to/msulaimanmisri/bm-tips-untuk-naik-gaji-bagi-seorang-web-developer-3ob1</guid>
      <description>&lt;p&gt;Assalamualaikum dan Hai semua. Seperti yang saya janjikan pada posting di Facebook, saya akan kongsikan kepada kalian bagaimana saya 'Hack' diri sendiri untuk mendapatkan kenaikan gaji setiap tahun bersama 3 syarikat yang saya bekerja.&lt;/p&gt;

&lt;p&gt;Anda boleh rujuk posting saya disini : &lt;a href="https://www.facebook.com/photo/?fbid=1613914802384682&amp;amp;set=a.120422831733894&amp;amp;notif_id=1674139551199863&amp;amp;notif_t=feedback_reaction_generic&amp;amp;ref=notif" rel="noopener noreferrer"&gt;Facebook Sulaiman&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Penafian : Hasil (Result) mungkin berbeza. Kena faham sangat konsep REZEKI. Ini adalah ikhtiar sahaja. Yang menentukan segala-galanya adalah yang maha Esa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Berbalik pada tajuk yang dikarang, bagaimana anda boleh menerima kenaikkan gaji setiap tahun sebagai seorang Web Developer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web Developer yang dimaksudkan dalam posting ini termasuklah App Developer, Software Engineer, Data Scientist, dan yang melibatkan Coding.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Apa yang saya kongsikan ini adalah semata-mata berdasarkan pengalaman saya. Dengan tips ini, saya menerima kenaikkan gaji dari 2 syarikat dan 1 syarikat lagi saya tak naik gaji tetapi mendapat skop kerja yang lebih terperinci.&lt;/p&gt;

&lt;p&gt;2 syarikat yang saya menerima kenaikkan gaji ini pula, syarikat pertama saya menerima kenaikkan 12%. Manakala syarikat kedua saya menerima dua kali kenaikkan gaji dengan kadar 28% dan 43%.&lt;/p&gt;




&lt;h3&gt;
  
  
  Kenapa anda perlu buat perkara ini?
&lt;/h3&gt;

&lt;p&gt;Pertama adalah kerana Manager, Higher management syarikat anda tidak tahu apa yang anda inginkan dalam kerjaya. Terkadang apa yang anda buat pun mereka tak ingat.&lt;/p&gt;

&lt;p&gt;Yang mereka ingat adalah anda boleh buat atau tidak. Itu saja.&lt;/p&gt;

&lt;p&gt;Dan kita sebagai pekerja, tidak boleh salahkan mereka kerana mereka sudah ada banyak tugasan mereka sendiri.&lt;/p&gt;

&lt;p&gt;Kedua, anda bertanggungjawab sepenuhnya tentang kerjaya anda. Bukan orang lain.&lt;/p&gt;

&lt;p&gt;Ketiga, syarikat perlukan sebab-musabab kenapa perlu menaikkan gaji anda. Jadi anda perlu tunjukkan Value (nilai) yang ada pada diri anda.&lt;/p&gt;




&lt;p&gt;Apa yang anda perlu laksanakan untuk membolehkan anda menerima kenaikkan gaji?&lt;/p&gt;

&lt;h3&gt;
  
  
  Pertama. Matlamat
&lt;/h3&gt;

&lt;p&gt;Anda perlu tetapkan matlamat yang jelas dalam hala tuju kerjaya anda. Anda kena jelas apa yang anda nak capai. Jika anda nak jadi CTO atau gaji RM100K / bulan, bila anda nak perkara tu terjadi?&lt;/p&gt;

&lt;p&gt;Kemudian, anda pecahkan kepada perkara yang kecil apa yang anda perlu buat demi mencapai matlamat yang utama itu tadi.&lt;/p&gt;

&lt;p&gt;Sebagai contoh, saya mahu menjadi seorang CTO (Chief Technology Officer) dengan gaji sebanyak RM30K sebulan pada tahun 2030. Untuk menjadi seorang CTO, saya mesti kena faham perkara yang berkait dengan Teknologi. Jadi setiap tahun, saya kena fokus apa yang saya nak belajar, faham dan amalkan.&lt;/p&gt;

&lt;p&gt;Sekarang saya berada di tahun 2023, jadi pada tahun ini apa yang saya perlu lakukan. Tahun hadapan apa? 2 tahun hadapan? Dan seterusnya.&lt;/p&gt;

&lt;p&gt;Untuk memudahkan anda menentukan matlamat ni, anda boleh Google apa itu Vision Board.&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%2Fcdbw75uwmw15rauoy7p1.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%2Fcdbw75uwmw15rauoy7p1.png" alt="Image description" width="692" height="692"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Kedua. Bertindak.
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Perbezaan antara orang yang gagal dan orang yang berjaya adalah, orang berjaya dia bertindak selepas dia buat perancangan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jadi anda perlu bertindak selepas anda melaksanakan Langkah pertama. Anda tahu untuk menjadi seorang Senior Front-end Developer, anda wajib untuk tahu salah satu Libraries/Frameworks JS diluar sana. Maka anda terus bertindak dengan belajar atau buat projek yang akan mendekatkan diri anda dekat matlamat yang hendak dicapai.&lt;/p&gt;

&lt;p&gt;** Projek disini boleh jadi projek bersama syarikat atau projek tepi. Jika saya, saya akan buat projeck tepi yang ada kaitan dengan syarikat. Pada langkah ke-empat saya akan perincikan.&lt;/p&gt;

&lt;p&gt;Langkah ini wajib selaras dengan langkah pertama. Kena align.&lt;/p&gt;




&lt;h3&gt;
  
  
  Ketiga. Track &amp;amp; Record
&lt;/h3&gt;

&lt;p&gt;Selepas anda bersungguh-sungguh untuk laksanakan langkah kedua, anda wajib Track &amp;amp; Record supaya anda tahu anda tidak lari dari landasan yang anda telah bina.&lt;/p&gt;

&lt;p&gt;Gunakan platform yang boleh anda track &amp;amp; record. Contohnya saya ingin menjadi seorang WordPress Specialist. Jadi saya perlu mahir dalam JavaScript, PHP &amp;amp; SQL (Kerana dengan tiga ini, saya boleh buat pelbagai perkara dengan WordPress).&lt;/p&gt;

&lt;p&gt;Jadi saya track &amp;amp; record segala Customization, Plugins, Themes yang telah saya buat.&lt;/p&gt;




&lt;h3&gt;
  
  
  Keempat. Show. Don't tell.
&lt;/h3&gt;

&lt;p&gt;Ini adalah masanya untuk anda buktikan bahawasanya, anda adalah asset kepada syarikat. Anda ada value yang boleh membantu syarikat menjana kekayaan.&lt;/p&gt;

&lt;p&gt;Dalam ketiga-tiga syarikat yang saya sertai. Saya adalah orang pertama yang melaksanakan perkara ini. Saya ada manager, saya ada director. Saya tempah masa mereka 1 - 2 bulan awal untuk mereka luangkan masa untuk saya bentangkan Track &amp;amp; Record saya.&lt;/p&gt;

&lt;p&gt;Setiap tahun saya akan book pada hujung Disember kerana pada waktu ini kerana pada saya, ini masa yang sesuai sebelum masuk ke tahun baru. Dan sinonim dengan Masuk tahun baru dengan Azam yang baru.&lt;/p&gt;

&lt;p&gt;Pada sesi ini, anda wajib untuk bentangkan segala data yang anda buat semasa langkah ketiga yakni Track &amp;amp; Record.&lt;/p&gt;

&lt;p&gt;Anda kena kongsikan data yang berjaya dan yang tidak berjaya. Anda kena buat satu Presentation dan bincangan secara terperinci apa yang telah anda laksanakan sepanjang 12 bulan anda bekerja.&lt;/p&gt;




&lt;h3&gt;
  
  
  Kelima. Kongsikan matlamat
&lt;/h3&gt;

&lt;p&gt;Pada langkah ke-empat, anda jangan hanya sekadar beritahu tentang Track &amp;amp; Record anda. Tetapi yang paling penting, anda kena kongsi matlamat kerjaya anda.&lt;/p&gt;

&lt;p&gt;Dari sini anda boleh tahu adakah Syarikat boleh berikan peluang untuk anda mencapai matlamat yang anda inginkan. Jika syarikat tidak boleh untuk menawarkan peluang untuk anda capai matlamat kerjaya. Tidak mengapa. Mungkin syarikat lain boleh.&lt;/p&gt;

&lt;p&gt;Anda tak perlu kongsi Matlamat utama anda Seperti nak jadi CTO. tapi kongsi yang kecil sahaja. Sebagai contoh, Saya nak mahir dalam beberapa perkara pada tahun hadapan seperti API, Server, Cloud Storage dan lain-lain.&lt;/p&gt;




&lt;p&gt;Nah.. Inilah perkara yang saya laksanakan dari dahulu sehingga sekarang. Setiap tahun. Apa yang saya belajar daripada semua ini adalah, syarikat nak lihat Nilai yang ada pada diri anda. Adakah Nilai itu berbaloi untuk mereka naikkan gaji anda? Atau naikkan pangkat anda?&lt;/p&gt;

&lt;p&gt;Saya lihat ramai rakan-rakan Developer saya sekadar kerja. Sekadar harapkan gaji hujung bulan. Kalau tak cukup, mengeluh. Tapi apa tindakan pun tak diambil untuk memperbaiki hidup.&lt;/p&gt;

&lt;p&gt;Saya pun dulu begitu. Selesa dengan tugasan. Tidak mahu keluar dari ruang selesa. Tidak mahu buat perkara baru seperti Coding untuk Front-end (sebab saya fokus ke Back-end). Tapi kalau bercerita tentang gaji, sibuk kata tak cukup.&lt;/p&gt;

&lt;p&gt;Saya harap langkah ini anda dapat laksanakan demi mencapai apa yang anda inginkan dalam kerjaya. Nak jadi seorang Senior Developer pun, ada perjalannya (path). Apatah lagi nak capai Gaji RM30K sebulan. Tak gitu.&lt;/p&gt;

&lt;p&gt;Saya kongsikan Google Slide yang saya buat semasa perbentangan saya dengan Syarikat saya bekerja sekarang.&lt;/p&gt;

&lt;p&gt;** Saya buang nama syarikat, gambar syarikat dan nama klien.&lt;/p&gt;

&lt;p&gt;Slide 1. Result - Kenaikkan gaji 28% : &lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/1Y5RltFFqBWQYVSIzHmmTOgtQ59smbmQ_/edit?usp=sharing&amp;amp;ouid=107472174074672390160&amp;amp;rtpof=true&amp;amp;sd=true" rel="noopener noreferrer"&gt;Google Slide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slide 2. Result - Kenaikkan gaji 43% : &lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/1Gdb91nH-o1QqvgKtANDTn6eOcUXPxe3T/edit?usp=sharing&amp;amp;ouid=107472174074672390160&amp;amp;rtpof=true&amp;amp;sd=true" rel="noopener noreferrer"&gt;Google Slide&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Saya harap guideline ini bermanfaaat kepada rakan-rakan developer.&lt;/p&gt;

&lt;p&gt;Sekiranya anda ada persoalan, bolehlah bertanya dibawah. Saya akan sedaya updaya untuk menjawab soalan anda.&lt;/p&gt;

&lt;p&gt;Terima kasih kerana sudi membaca.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>salary</category>
    </item>
    <item>
      <title>How to enable user to upload profile photo in Laravel 8</title>
      <dc:creator>Muhamad Sulaiman</dc:creator>
      <pubDate>Tue, 11 Jan 2022 16:01:55 +0000</pubDate>
      <link>https://dev.to/msulaimanmisri/how-to-enable-user-to-upload-profile-photo-in-laravel-8-52k3</link>
      <guid>https://dev.to/msulaimanmisri/how-to-enable-user-to-upload-profile-photo-in-laravel-8-52k3</guid>
      <description>&lt;p&gt;Today I was assigned to develop a user profile function in our client web apps.&lt;/p&gt;

&lt;p&gt;Ok, easy enough. I just need a form that has enctype and file upload.&lt;/p&gt;

&lt;p&gt;So I thought it only needs to upload the image, then store it in DB and then show it to the front-end.&lt;/p&gt;

&lt;p&gt;However, the flow that I thought is wrong. The flow should be very seamless. Which is when the user success registers, they can see the default profile image (set by the system, like example image). Then when users click on the image, their windows appear, choose the image and then save.&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%2F63thmuk5pbnle1rsvrf9.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%2F63thmuk5pbnle1rsvrf9.png" alt="UIX-User-Profile" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The save button should not like the default file upload (refer to Bootstrap File Input).&lt;/p&gt;

&lt;p&gt;Also, after the user click Save Photo, the system will behave like SPA. Without refreshing the browser.&lt;/p&gt;

&lt;p&gt;That time I know I was in trouble. Because I don't like much play around with JavaScript. I know I can achieve that using vanilla or JS Framework such as Inertia or Vue. I'm using Laravel by the way.&lt;/p&gt;

&lt;p&gt;So after searching, I decide to use Laravel Livewire. Why?&lt;/p&gt;

&lt;p&gt;This is mainly because I think I can make it using Livewire and not others.  And the best part of Livewire is that even though I code dynamic function for Front-end, but I'm coding it using PHP Laravel. I don't know if this makes any sense to you.&lt;/p&gt;

&lt;p&gt;So how do I develop it using Livewire?&lt;/p&gt;

&lt;p&gt;First, after I create the component, I create a method named avatar() on User Class.&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%2F9gqzqyzzy9x513ipvh8e.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%2F9gqzqyzzy9x513ipvh8e.png" alt="Avatar-method-syntax" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second, in the livewire component, I use the file upload trait (because Livewire does not support file upload by default).&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%2F8naq9up5g86f3i8ciey2.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%2F8naq9up5g86f3i8ciey2.png" alt="livewire-trait-syntax" width="800" height="921"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I create a method to save the avatar when the user uploaded it. Don't forget to set the avatar null to remove the button right after user successfully upload the image.&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%2Fddlo7pvutae41qvvavpp.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%2Fddlo7pvutae41qvvavpp.png" alt="Save-method-syntax" width="800" height="606"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Third, in my rendering component file, I show the default image first. Then after the user saves, the image will change into a new image.&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%2Fkdqzcl65x4xh9w0ple3n.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%2Fkdqzcl65x4xh9w0ple3n.png" alt="Livewire-rendering-component-syntax" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it. With all of these steps, you now will have a User profile functionality.&lt;/p&gt;

&lt;p&gt;I've complete the task. Now your turn to do it better than me. Share your experience in the comment section ;)&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>livewire</category>
    </item>
  </channel>
</rss>
