<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shamsuddeen Abdulkadir</title>
    <description>The latest articles on Forem by Shamsuddeen Abdulkadir (@eldeeno).</description>
    <link>https://forem.com/eldeeno</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%2F207388%2F5810ad4f-675a-470c-a197-c74c266cba0d.jpeg</url>
      <title>Forem: Shamsuddeen Abdulkadir</title>
      <link>https://forem.com/eldeeno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/eldeeno"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Shamsuddeen Abdulkadir</dc:creator>
      <pubDate>Sun, 19 Oct 2025 16:57:43 +0000</pubDate>
      <link>https://forem.com/eldeeno/-2pgm</link>
      <guid>https://forem.com/eldeeno/-2pgm</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d" class="crayons-story__hidden-navigation-link"&gt;Laravel APP_KEY vs Password Hashing: What Every Developer Should Know About Encryption &amp;amp; Hashing.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/eldeeno" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F207388%2F5810ad4f-675a-470c-a197-c74c266cba0d.jpeg" alt="eldeeno profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/eldeeno" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Shamsuddeen Abdulkadir
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Shamsuddeen Abdulkadir
                
              
              &lt;div id="story-author-preview-content-2940704" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/eldeeno" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F207388%2F5810ad4f-675a-470c-a197-c74c266cba0d.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Shamsuddeen Abdulkadir&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 19 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d" id="article-link-2940704"&gt;
          Laravel APP_KEY vs Password Hashing: What Every Developer Should Know About Encryption &amp;amp; Hashing.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/security"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;security&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/laravel"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;laravel&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/php"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;php&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>security</category>
      <category>laravel</category>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>Laravel APP_KEY vs Password Hashing: What Every Developer Should Know About Encryption &amp; Hashing.</title>
      <dc:creator>Shamsuddeen Abdulkadir</dc:creator>
      <pubDate>Sun, 19 Oct 2025 16:57:25 +0000</pubDate>
      <link>https://forem.com/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d</link>
      <guid>https://forem.com/eldeeno/laravel-appkey-vs-password-hashing-what-every-developer-should-know-about-encryption-hashing-2d7d</guid>
      <description>&lt;p&gt;It was 1:45PM on a Sunday afternoon. I was having a discussion about TLS/SSL with my wife, who happened to be a Senior Cybersecurity Consultant at one of the Big-Fours, when the topic of hashing and encryption crept into the conversation. Most of my thoughts during the conversation revolved around software development — I mean, it is what I do. &lt;/p&gt;

&lt;p&gt;I have been developing solutions with the Laravel framework for a while now, but I have little idea of how encryption works in detail. All I know is that it uses the key generated during installation in the .env file, &lt;code&gt;APP_KEY&lt;/code&gt;, for encryption. I also know about secure password hashing using Bcrypt driver: &lt;code&gt;Hash::make('password')&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;However, I never paid detailed attention to the topic of encryption and its difference from hashing, especially in relation to Laravel and security in software systems. I was had a misconception that the app key is also used in password hashing before this whole conversation — just like the creator of the Laravel framework, Taylor Otwell, clarified years back on &lt;a href="https://x.com/taylorotwell/status/1027290106648875008" rel="noopener noreferrer"&gt;Twitter, now X&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is a breakdown of my findings about Encryption, Hashing and the difference between the two. And also how they're utilized in Laravel framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encryption
&lt;/h2&gt;

&lt;p&gt;This is said to be a two-way function, meaning whatever data you encrypt can be decrypted. This is what the env variable &lt;code&gt;APP_KEY&lt;/code&gt; is used for in Laravel. It is used for securing storage such as cookies, session data, API tokens, and more.&lt;br&gt;
A simple example is; When a user is authenticated in a Laravel Application, the cookies and session data is encrypted using the current APP_KEY. When a new key is generated, then the user gets automatically logged out of the application. &lt;br&gt;
Below is a simple example from the &lt;a href="https://laravel.com/docs/12.x/encryption" rel="noopener noreferrer"&gt;Laravel documentation&lt;/a&gt; on encrypting a string:&lt;br&gt;
&lt;/p&gt;

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

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;

class DigitalOceanTokenController extends Controller
{
    /**
     * Store a DigitalOcean API token for the user.
     */
    public function store(Request $request): RedirectResponse
    {
        $request-&amp;gt;user()-&amp;gt;fill([
            'token' =&amp;gt; Crypt::encryptString($request-&amp;gt;token),
        ])-&amp;gt;save();

        return redirect('/secrets');
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hashing
&lt;/h2&gt;

&lt;p&gt;Hashing, on the other hand, is a one-way function. This means that when data is hashed, it cannot be reversed to its original form. This is used mainly to store data that can be verified but not in its original form. For example, hashing a user's password and then storing the hashed form of the password in the database. Whoever that has access to the records cannot tell what the password is because it hashed. And then during Authentication, the password entered by the user will be hashed first, and then compared with the one stored in database.&lt;br&gt;
The default hashing driver is used in the &lt;a href="https://laravel.com/docs/12.x/hashing" rel="noopener noreferrer"&gt;Laravel framework&lt;/a&gt; is Bcrypt.&lt;br&gt;
Below is a very snippet from the documentation that depicts the most common hashing implementation:&lt;br&gt;
&lt;/p&gt;

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

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class PasswordController extends Controller
{
    /**
     * Update the password for the user.
     */
    public function update(Request $request): RedirectResponse
    {
        // Validate the new password length...

        $request-&amp;gt;user()-&amp;gt;fill([
            'password' =&amp;gt; Hash::make($request-&amp;gt;newPassword)
        ])-&amp;gt;save();

        return redirect('/profile');
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope it is an interesting read and discovery for you as it was for me, that Encryption and Hashing are fundamentally different security concepts with different use cases in Laravel. See you on the next one!&lt;/p&gt;

</description>
      <category>security</category>
      <category>laravel</category>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>Load Testing a Non-API Laravel Web Application with Sanctum Session-Based Authentication Using K6</title>
      <dc:creator>Shamsuddeen Abdulkadir</dc:creator>
      <pubDate>Sun, 19 May 2024 21:23:54 +0000</pubDate>
      <link>https://forem.com/eldeeno/load-testing-a-non-api-laravel-web-application-with-sanctum-session-based-authentication-using-k6-39dn</link>
      <guid>https://forem.com/eldeeno/load-testing-a-non-api-laravel-web-application-with-sanctum-session-based-authentication-using-k6-39dn</guid>
      <description>&lt;p&gt;The idea for this post came from a project I handled at work, where I needed to load test a high-demand platform. I initially started with &lt;strong&gt;Jmeter&lt;/strong&gt; based on colleagues' recommendations but encountered issues with Sanctum session authentication tokens. Despite multiple attempts, I couldn't resolve the problem.&lt;/p&gt;

&lt;p&gt;The aim of this tutorial is not to introduce you to Load Testing or K6 but rather, to offer a solution for those facing similar issues with passing Sanctum session token in their tests, so they wouldn't go through the stress I experienced.&lt;br&gt;
Upon researching about other alternatives to Jmeter, I discovered &lt;strong&gt;K6&lt;/strong&gt;, an open-source load testing tool.&lt;/p&gt;

&lt;p&gt;Testing an endpoint that required Sanctum session-based authentication proved challenging, particularly when handling the XSRF-TOKEN. I searched extensively for solutions on integrating Sanctum with K6 but found none. This led me to create my own approach, which I'm sharing here.&lt;/p&gt;

&lt;p&gt;Below is the sample K6 test code and it is easy to understand for those with basic understanding of K6 and Javascript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { parseHTML } from 'k6/html';
import { sleep, group, check } from "k6";
import http from 'k6/http';

export const options = {
    stages: [
        { target: 50, duration: '1m' },
        { target: 100, duration: '0' },
        { target: 200, duration: '1m30s' },
    ],
}

// Login credentials
const jsonData = JSON.parse(open('./data.json')).users;

export default function main() {
    let response;
    let token;

    group('get login page', function () {
        response = http.get('https://your-domain/login');

        let xsrfTokenValue = null;
        let cookies = response.headers['Set-Cookie'];
        if (cookies) {
            let cookieArray = cookies.split(';');
            cookieArray.forEach(cookie =&amp;gt; {
                if (cookie.includes('XSRF-TOKEN')) {
                    xsrfTokenValue = cookie.split('=')[1].replace(/%3D$/, ''); // Remove '=%3D' from the end
                }
            });

            token = xsrfTokenValue;
        }

        check(response, {
            'is status 200': (r) =&amp;gt; r.status === 200,
            'XSRF-TOKEN exists': (t) =&amp;gt; t !== null,
        });
    });

    sleep(10);

    group('post login page', function () {

        const payload = JSON.stringify({
            username: jsonData[0].username,
            password: jsonData[0].password,
        });

        const params = {
            headers: {
                Connection: 'keep-alive',
                'Content-Type': 'application/json',
                'X-XSRF-TOKEN': token,
            },
        };

        const res = http.post('https://your-domain/login', payload, params);
        check(res, {
            'is status 200': (r) =&amp;gt; r.status === 200,
            'is correct URL': (r) =&amp;gt; r.url === 'https://your-domain/welcome-page'
        });
    });

    sleep(10);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this solution helps you overcome the challenges of handling Sanctum session-based authentication in your load testing.&lt;br&gt;
If you have any questions or need further clarification, feel free to drop a comment. Happy testing!&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>k6</category>
      <category>testing</category>
      <category>session</category>
    </item>
    <item>
      <title>SOLID Principles in Laravel: A Beginner's Series</title>
      <dc:creator>Shamsuddeen Abdulkadir</dc:creator>
      <pubDate>Thu, 28 Mar 2024 22:16:33 +0000</pubDate>
      <link>https://forem.com/eldeeno/solid-principles-in-laravel-a-beginners-series-22d9</link>
      <guid>https://forem.com/eldeeno/solid-principles-in-laravel-a-beginners-series-22d9</guid>
      <description>&lt;p&gt;&lt;em&gt;Robert C. Martin&lt;/em&gt;, also known as &lt;em&gt;Uncle Bob&lt;/em&gt;, emphasizes in his book &lt;strong&gt;Clean Architecture&lt;/strong&gt; the importance of good code as the foundation of good software systems. He compares well-made code to high-quality bricks in building construction. Even with excellent architectural plans, poorly made bricks can undermine the entire structure. On the other hand, well-made bricks can still result in a messy construction if not assembled properly. This is where &lt;strong&gt;SOLID principles&lt;/strong&gt; play a crucial role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOLID&lt;/strong&gt; is an acronym representing five fundamental principles in object-oriented programming and design. Let's break it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;S stands for Single Responsibility Principle (SRP)&lt;/li&gt;
&lt;li&gt;O stands for Open/Closed Principle (OCP)&lt;/li&gt;
&lt;li&gt;L stands for Liskov Substitution Principle (LSP)&lt;/li&gt;
&lt;li&gt;I stands for Interface Segregation Principle (ISP)&lt;/li&gt;
&lt;li&gt;D stands for Dependency Inversion Principle (DIP)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These principles, coined by Robert C. Martin, provide guidelines for writing clean, maintainable, and extensible code. Each principle focuses on a specific aspect of software design, aiming to improve modularity, flexibility, and scalability. Understanding and applying these principles can lead to more robust and adaptable software systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;&lt;br&gt;
In this series kickoff, we'll explore SRP with example using PHP &amp;amp; &lt;a href="https://laravel.com/" rel="noopener noreferrer"&gt;Laravel&lt;/a&gt; framework, showcasing how it fosters cleaner, more maintainable code. &lt;br&gt;
The Single Responsibility Principle (SRP) emphasizes that a class or method should have only one reason to change, meaning it should have a single responsibility or purpose. By adhering to SRP, we ensure that each entity in our codebase is focused on doing one thing well, making our code more maintainable, understandable, and flexible.&lt;/p&gt;

&lt;p&gt;Imagine writing a Laravel controller for product management that not only validates &amp;amp; store product data but also dispatches email notifications to interested customers.&lt;br&gt;
&lt;/p&gt;

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

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\ProductRequestedNotification;

class ProductController extends Controller
{
    public function store(Request $request)
    {
        // Validation rules
        $validatedData = $request-&amp;gt;validate([
            'name' =&amp;gt; 'required|string|max:255',
            'description' =&amp;gt; 'required|string',
            'price' =&amp;gt; 'required|numeric|min:0',
            'quantity' =&amp;gt; 'required|integer|min:0',
            'email' =&amp;gt; 'required|email',
        ]);

        // Create new product
        $product = Product::create([
            'name' =&amp;gt; $validatedData['name'],
            'description' =&amp;gt; $validatedData['description'],
            'price' =&amp;gt; $validatedData['price'],
            'quantity' =&amp;gt; $validatedData['quantity'],
        ]);

        // Send notification to customer
        Mail::to($validatedData['email'])-&amp;gt;send(new ProductRequestedNotification($product));

        // Return success response
        return response()-&amp;gt;json(['message' =&amp;gt; 'Product stored successfully'], 200);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the provided example, the &lt;code&gt;ProductController&lt;/code&gt; is handling multiple responsibilities, including data validation, product storage, and email notification. This violates the Single Responsibility Principle (SRP), which states that a class should have only one reason to change.&lt;/p&gt;

&lt;p&gt;To adhere to SRP and improve the controller's clarity and extensibility, we can refactor it to delegate each responsibility to separate classes. This separation of concerns enhances maintainability and allows for easier extension in the future:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Request Validation: Extract the validation rules to a separate &lt;a href="https://laravel.com/docs/11.x/validation#creating-form-requests" rel="noopener noreferrer"&gt;request class&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Product Creation: Move the product creation logic to a &lt;a href="https://medium.com/@laravelprotips/understanding-laravel-service-classes-a-comprehensive-guide-1f22310c70bd" rel="noopener noreferrer"&gt;service class&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Notification: Handle the &lt;a href="https://laravel.com/docs/11.x/notifications" rel="noopener noreferrer"&gt;notification&lt;/a&gt; logic in a separate class.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, create a new Form Request class using the artisan command:&lt;br&gt;
&lt;code&gt;php artisan make:request StoreProductRequest&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will generate a new file &lt;code&gt;StoreProductRequest.php&lt;/code&gt; in the &lt;code&gt;app/Http/Requests&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;StoreProductRequest.php&lt;/code&gt; file and update the &lt;code&gt;rules()&lt;/code&gt; method with the validation rules:&lt;br&gt;
&lt;/p&gt;

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

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreProductRequest extends FormRequest
{
    public function authorize()
    {
        return true; // Authorization logic can be added if needed
    }

    public function rules()
    {
        return [
            'name' =&amp;gt; 'required|string|max:255',
            'description' =&amp;gt; 'required|string',
            'price' =&amp;gt; 'required|numeric|min:0',
            'quantity' =&amp;gt; 'required|integer|min:0',
            'email' =&amp;gt; 'required|email',
        ];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create the &lt;code&gt;ProductService&lt;/code&gt; class, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the app/Http/ directory in your Laravel application.&lt;/li&gt;
&lt;li&gt;Create a new folder named &lt;code&gt;Services&lt;/code&gt; if it doesn't exist already.&lt;/li&gt;
&lt;li&gt;Inside the &lt;code&gt;Services&lt;/code&gt; folder, create a new file named &lt;code&gt;ProductService.php&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open the &lt;code&gt;ProductService.php&lt;/code&gt; file and add the following code:
&lt;/li&gt;
&lt;/ol&gt;

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

namespace App\Services;

use App\Models\Product;

class ProductService
{
    public function create(array $data): Product
    {
        return Product::create([
            'name' =&amp;gt; $data['name'],
            'description' =&amp;gt; $data['description'],
            'price' =&amp;gt; $data['price'],
            'quantity' =&amp;gt; $data['quantity'],
        ]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we will generate a &lt;a href="https://laravel.com/docs/11.x/notifications" rel="noopener noreferrer"&gt;Laravel Notification&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

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

namespace App\Notifications;

use App\Models\Product;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class ProductRequestedNotification extends Notification implements ShouldQueue
{
    use Queueable;

    protected $product;

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

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
            -&amp;gt;line('Your product request has been received successfully.')
            -&amp;gt;line('Product Name: ' . $this-&amp;gt;product-&amp;gt;name)
            -&amp;gt;line('Description: ' . $this-&amp;gt;product-&amp;gt;description)
            -&amp;gt;line('Price: ' . $this-&amp;gt;product-&amp;gt;price)
            -&amp;gt;line('Quantity: ' . $this-&amp;gt;product-&amp;gt;quantity);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the &lt;code&gt;ProductController&lt;/code&gt; looks like after refactoring:&lt;br&gt;
&lt;/p&gt;

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

namespace App\Http\Controllers;

use App\Http\Requests\ProductRequest;
use App\Services\ProductService;
use App\Notifications\ProductRequestedNotification;

class ProductController extends Controller
{
    protected $productService;

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

    public function store(ProductRequest $request)
    {
        // Create new product
        $product = $this-&amp;gt;productService-&amp;gt;create($request-&amp;gt;validated());

        // Send notification to customer
        $product-&amp;gt;notify(new ProductRequestedNotification($product));

        // Return success response
        return response()-&amp;gt;json(['message' =&amp;gt; 'Product stored successfully'], 200);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this refactoring, the &lt;code&gt;ProductController&lt;/code&gt; is now responsible only for handling HTTP requests and responses, while the validation rules are encapsulated in the &lt;code&gt;StoreProductRequest&lt;/code&gt; class, the email notification is handled by &lt;code&gt;ProductRequestedNotification&lt;/code&gt; class, and the business logic for creating a product is handled by the &lt;code&gt;ProductService&lt;/code&gt; class. This separation of concerns improves code readability, maintainability, and testability.&lt;/p&gt;

&lt;p&gt;In the upcoming part of the series, we'll delve into another fundamental principle: the &lt;strong&gt;Open/Closed Principle&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>softwareengineering</category>
      <category>php</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
