<?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: Ian Kumu</title>
    <description>The latest articles on Forem by Ian Kumu (@iankumu).</description>
    <link>https://forem.com/iankumu</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%2F890487%2F11805b33-08b1-4126-93b3-9fc19ada4d25.png</url>
      <title>Forem: Ian Kumu</title>
      <link>https://forem.com/iankumu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/iankumu"/>
    <language>en</language>
    <item>
      <title>How to Build a Rest API with Laravel: A Beginners Guide</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Sat, 19 Nov 2022 13:01:36 +0000</pubDate>
      <link>https://forem.com/iankumu/how-to-build-a-rest-api-with-laravel-a-beginners-guide-2fjm</link>
      <guid>https://forem.com/iankumu/how-to-build-a-rest-api-with-laravel-a-beginners-guide-2fjm</guid>
      <description>&lt;p&gt;With the rise of mobile and javascript web frameworks such as &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue&lt;/a&gt;, Restful APIs have seen their popularity increase. This is because you can maintain one backend serving multiple front-end clients.&lt;/p&gt;

&lt;p&gt;Laravel provides a good environment and ecosystem for building your Rest API.&lt;/p&gt;

&lt;p&gt;First-party packages such as &lt;a href="https://www.iankumu.com/blog/laravel-passport/" rel="noopener noreferrer"&gt;Laravel Passport&lt;/a&gt; and &lt;a href="https://www.iankumu.com/blog/laravel-sanctum/" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt; provide &lt;strong&gt;API authentication implementation making authentication easy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/9.x/starter-kits#laravel-breeze" rel="noopener noreferrer"&gt;Laravel Breeze&lt;/a&gt; provides starter templates that can help with reset password features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/9.x/socialite" rel="noopener noreferrer"&gt;Socialite&lt;/a&gt; and &lt;a href="https://laravel.com/docs/9.x/scout" rel="noopener noreferrer"&gt;Scout&lt;/a&gt; provide &lt;a href="https://www.iankumu.com/blog/laravel-socialite/" rel="noopener noreferrer"&gt;Social Login&lt;/a&gt; implementations and &lt;a href="https://www.iankumu.com/blog/laravel-search/" rel="noopener noreferrer"&gt;Full-text search&lt;/a&gt; functionalities.&lt;/p&gt;

&lt;p&gt;The laravel ecosystem provides solutions to almost all problems you can encounter in your development journey thus &lt;strong&gt;providing maximum productivity&lt;/strong&gt; to a developer.&lt;/p&gt;

&lt;p&gt;This tutorial will explore &lt;strong&gt;how to create a Laravel Rest API with authentication using Laravel Sanctum&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Restful API?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/what-is/restful-api/" rel="noopener noreferrer"&gt;REST&lt;/a&gt; stands for REpresentational State Transfer and it is a pattern used for communication between applications through HTTP. The protocol is stateless meaning no session is stored between the applications. Each request is therefore processed as if it is a new request even though it is repeated.&lt;/p&gt;

&lt;p&gt;A benefit of REST APIs is that they can &lt;strong&gt;easily be cached&lt;/strong&gt;. It is easy to &lt;a href="https://www.iankumu.com/blog/laravel-cache/" rel="noopener noreferrer"&gt;cache a response&lt;/a&gt; from the Rest API in a service such as Redis or Memcached and thus easy to scale.&lt;/p&gt;

&lt;p&gt;For an API to be considered Restful, it has to have the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be accessible over a URL or endpoint &lt;/li&gt;
&lt;li&gt;Must use any of the REST Methods &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common REST Methods are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GET&lt;/strong&gt; -Fetch resources from an API&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;POST&lt;/strong&gt; -Create a resource in the API&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PUT/PATCH&lt;/strong&gt; -Update a resource in the API&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DELETE&lt;/strong&gt; – Delete a resource from an API&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can have HTTP headers &lt;/li&gt;
&lt;li&gt;Must return a valid response code in each response. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to build a REST API with Laravel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a new Application
&lt;/h3&gt;

&lt;p&gt;The first step is to create a new Laravel application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;laravel new rest 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set up a Model and Migration
&lt;/h3&gt;

&lt;p&gt;The next step is to create a Model and its corresponding migration file. This acts as a blueprint for our database table. In this tutorial, I will use &lt;strong&gt;Products&lt;/strong&gt; as my resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Products &lt;span class="nt"&gt;-m&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The -m flag will instruct Laravel to create the corresponding migration file of the Products Model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Models/Products
&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\Models&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\Database\Eloquent\Factories\HasFactory&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\Database\Eloquent\Model&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;Products&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&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;The migration file generated will resemble the one below.&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;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&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\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Run the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&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;'products'&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;timestamps&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;/**
     * Reverse the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&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;We can start by &lt;strong&gt;updating the migration file&lt;/strong&gt; by adding more columns to our database. I will add the following columns: product &lt;strong&gt;name&lt;/strong&gt; , product &lt;strong&gt;price&lt;/strong&gt; and product &lt;strong&gt;description&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&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\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Run the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&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;'products'&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;'name'&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;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;longText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&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;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Reverse the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&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;We can then &lt;strong&gt;update the Products model&lt;/strong&gt; by registering the &lt;strong&gt;mass-assignable variables&lt;/strong&gt;. This helps prevent SQL injection by instructing laravel only to accept data containing the specified keys/variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Models/Products
&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\Models&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\Database\Eloquent\Factories\HasFactory&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\Database\Eloquent\Model&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;Products&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&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;The last step is to &lt;strong&gt;set up the database credentials&lt;/strong&gt; in the &lt;strong&gt;.env&lt;/strong&gt; file and &lt;strong&gt;create the database&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-rest
DB_USERNAME=root
DB_PASSWORD=password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to migrate the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan migrate 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Database Seeder and Factory
&lt;/h3&gt;

&lt;p&gt;When developing, I prefer to &lt;strong&gt;use fake data&lt;/strong&gt; to ensure that I develop &lt;strong&gt;as fast as possible&lt;/strong&gt;. Laravel provides a handy &lt;strong&gt;Factory facade&lt;/strong&gt; that can allow us to use &lt;a href="https://github.com/fzaninotto/Faker" rel="noopener noreferrer"&gt;Faker&lt;/a&gt; to generate dummy data.&lt;/p&gt;

&lt;p&gt;We can run this command to create a Factory&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will create a file in the &lt;strong&gt;databases/factories&lt;/strong&gt; folder&lt;/p&gt;

&lt;p&gt;We can update the file as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//database/factories/ProductsFactory
&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;Database\Factories&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\Database\Eloquent\Factories\Factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory&amp;lt;\App\Models\Products&amp;gt;
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductsFactory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Define the model's default state.
     *
     * @return array&amp;lt;string, mixed&amp;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;definition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;numberBetween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sentence&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;Now that our factory is ready, we can call it in the DatabaseSeeder file to seed our database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//database/seeders/DatabaseSeeder
&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;Database\Seeders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// use Illuminate\Database\Console\Seeds\WithoutModelEvents;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Seeder&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;DatabaseSeeder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Seeder&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Seed the application's database.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;\App\Models\Products&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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="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;We can now seed the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan db:seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a Controller
&lt;/h3&gt;

&lt;p&gt;Let’s now create a Controller which will contain all the Business logic for the API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:controller ProductsController &lt;span class="nt"&gt;-r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The -r flag will generate a Controller that is resourceful. This means it will create a controller with all the required methods for a Restful API.&lt;/p&gt;

&lt;p&gt;The main methods we will use are &lt;strong&gt;index&lt;/strong&gt; , &lt;strong&gt;show&lt;/strong&gt; , &lt;strong&gt;store&lt;/strong&gt; , &lt;strong&gt;update&lt;/strong&gt; and &lt;strong&gt;destroy&lt;/strong&gt;. We &lt;strong&gt;can delete&lt;/strong&gt; the &lt;strong&gt;create&lt;/strong&gt; and &lt;strong&gt;edit&lt;/strong&gt; methods as we will not need them. We can update the Products Controller as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Http/Controllers/ProductsController

&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\Http\Controllers&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\Http\Resources\ProductResource&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\Products&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\Http\Request&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;ProductsController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */&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;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Display the specified resource.
     *
     * @param Products $product
     * @return \Illuminate\Http\Response
     */&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;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param Products $product
     * @return \Illuminate\Http\Response
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Remove the specified resource from storage.
     *
     * @param Products $product
     * @return \Illuminate\Http\Response
     */&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;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;These methods can be mapped to the default HTTP verbs (get, post, patch/put and delete).&lt;/p&gt;

&lt;h4&gt;
  
  
  Index(Get all Products)
&lt;/h4&gt;

&lt;p&gt;We can use this method to &lt;strong&gt;return all products&lt;/strong&gt; present in the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Products&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;index&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="nc"&gt;Products&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can further customise it by paginating it or caching the response from the database.&lt;/p&gt;

&lt;h4&gt;
  
  
  Show(Get a Single Product)
&lt;/h4&gt;

&lt;p&gt;We can use this method to &lt;strong&gt;return a single product&lt;/strong&gt; present in the database&lt;/p&gt;

&lt;p&gt;We can pass the product id as a parameter and we can then fetch it from the database&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I am using API Resources which I will discuss later in the article.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Resources\ProductResource&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\Products&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;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Store(Create a Product)
&lt;/h4&gt;

&lt;p&gt;We can &lt;strong&gt;create a new product record&lt;/strong&gt; in the database using this method. A post method can be made to this method through an endpoint to create the record&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Resources\ProductResource&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\Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$product_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$product_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$product_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Products&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;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;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;'data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Update(Update Product Details)
&lt;/h4&gt;

&lt;p&gt;To &lt;strong&gt;update the product details&lt;/strong&gt; , we can update the logic of the update method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Resources\ProductResource&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\Products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$product_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$product_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'price'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$product_description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$product&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;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$product_description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;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;'data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ProductResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Destroy(Delete a Product)
&lt;/h4&gt;

&lt;p&gt;At times you might want to &lt;strong&gt;delete products&lt;/strong&gt; from the database. We can add the following code to delete products from the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Products&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;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Products&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;204&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;
  
  
  Routes and endpoints
&lt;/h3&gt;

&lt;p&gt;Let’s now create the endpoints that will be accessible over HTTP. We can add the routes in the &lt;strong&gt;routes/api.php&lt;/strong&gt; file&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\ProductsController&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\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/user'&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;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductsController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'index'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products.index'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products/{product}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductsController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'show'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products.show'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductsController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'store'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products.store'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products/{product}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductsController&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;'update'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products.update'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products/{product}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ProductsController&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;'destroy'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products.destroy'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;These endpoints are mapped to the methods in the ProductsController we created earlier.&lt;/p&gt;

&lt;p&gt;We can now test the index method through a GET request. This will return the following response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ut rerum aut deleniti eveniet ad et ullam perferendis."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-11-18T15:18:13.000000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-11-18T15:18:13.000000Z"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"maxime"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Natus officiis repellat vero ea voluptatem mollitia similique."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-11-18T15:18:13.000000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2022-11-18T15:18:13.000000Z"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Formatting the Response
&lt;/h3&gt;

&lt;p&gt;The response above is returned in JSON format. It includes details from the database with the column names as the keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if you want to format this response&lt;/strong&gt;? One thing you &lt;strong&gt;might not&lt;/strong&gt; want to expose is the &lt;strong&gt;created_at&lt;/strong&gt; and &lt;strong&gt;updated_at&lt;/strong&gt; data. You might also want to &lt;strong&gt;calculate and return&lt;/strong&gt; a predefined &lt;strong&gt;discount&lt;/strong&gt; back as a response.&lt;/p&gt;

&lt;p&gt;Laravel allows us to customize our responses using &lt;a href="https://laravel.com/docs/9.x/eloquent-resources" rel="noopener noreferrer"&gt;API resources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this example, I will assume that &lt;strong&gt;all products have a 10% discount&lt;/strong&gt;. I will therefore &lt;strong&gt;return the product price and the discounted price&lt;/strong&gt; as part of the payload in the response.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This will transform a model into an array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Http/Resources/ProductResource
&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\Http\Resources&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\Http\Resources\Json\JsonResource&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;ProductResource&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JsonResource&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'product_name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'product_price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"$"&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;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'discounted_price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"$"&lt;/span&gt; &lt;span class="mf"&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;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'discount'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"$"&lt;/span&gt; &lt;span class="mf"&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;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'product_description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;description&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;Let’s update our index method in Products Controller to use the Product resource&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;index&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="nc"&gt;ProductResource&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Products&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return the newly formatted response&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"quo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$15"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"discounted_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$13.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"discount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$1.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ut rerum aut deleniti eveniet ad et ullam perferendis."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"maxime"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$70"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"discounted_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$63"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"discount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"product_description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Natus officiis repellat vero ea voluptatem mollitia similique."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Response Codes
&lt;/h3&gt;

&lt;p&gt;It is important to always &lt;strong&gt;return a valid response code in each request&lt;/strong&gt;. These response codes can be used by a consuming application or client to know what exactly happened on the server side.&lt;/p&gt;

&lt;p&gt;Here is a list of the most common response codes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 – &lt;strong&gt;Ok&lt;/strong&gt;. This signifies it is a success code and it is the default response code &lt;/li&gt;
&lt;li&gt;201- &lt;strong&gt;Created&lt;/strong&gt;. This shows that a resource has been created. It is useful for POST requests. &lt;/li&gt;
&lt;li&gt;204- &lt;strong&gt;No Content&lt;/strong&gt;. This signifies that the action was successful but no content is returned. It is useful for DELETE requests since a deleted resource cannot return any body content &lt;/li&gt;
&lt;li&gt;400- &lt;strong&gt;Bad Request&lt;/strong&gt;. This signifies that the client passed an invalid request to the server &lt;/li&gt;
&lt;li&gt;401- &lt;strong&gt;Unauthorized&lt;/strong&gt;. This signifies that the client is not authorized to access the resource. It is typically used in authentication and authorization services. &lt;/li&gt;
&lt;li&gt;403- &lt;strong&gt;Forbidden&lt;/strong&gt;. This signifies that a user is authenticated but is not allowed to access the resource. &lt;/li&gt;
&lt;li&gt;404- &lt;strong&gt;Not Found&lt;/strong&gt;. This signifies that a resource is not found &lt;/li&gt;
&lt;li&gt;500- &lt;strong&gt;Internal Server Error&lt;/strong&gt;. This implies that there is an error at the server level &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Laravel allows us to specify the correct response code using the &lt;strong&gt;response()-&amp;gt;json()&lt;/strong&gt; helper function. It is important to always return a response code so that the client/frontend can display the correct data and “fail gracefully” in the case of an error.&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="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="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up Authentication with &lt;a href="https://iankumu.com/blog/laravel-sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We have discussed the most basic way of creating a CRUD REST API in Laravel. We now want to &lt;strong&gt;add authentication to our API&lt;/strong&gt; in order to secure it. There are two ways in which we can implement authentication; either through &lt;a href="https://iankumu.com/blog/laravel-passport" rel="noopener noreferrer"&gt;Laravel Passport&lt;/a&gt; or &lt;a href="https://iankumu.com/blog/laravel-sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://iankumu.com/blog/laravel-passport" rel="noopener noreferrer"&gt;Passport&lt;/a&gt;&lt;/strong&gt; provides a way in which &lt;strong&gt;applications authenticate themselves over the internet&lt;/strong&gt;. It basically adds &lt;strong&gt;Oauth implementation to your API&lt;/strong&gt; which other systems can use to authenticate themselves when interacting with your API. It is useful for &lt;strong&gt;public APIs&lt;/strong&gt; where you might want to track API usage and also limit requests for each API key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://iankumu.com/blog/laravel-sanctum" rel="noopener noreferrer"&gt;Sanctum&lt;/a&gt;&lt;/strong&gt; on the other hand provides a &lt;strong&gt;stateless integration of the normal authentication service&lt;/strong&gt; by &lt;strong&gt;using email and passwords to provide authentication&lt;/strong&gt; to a client. It is useful for &lt;strong&gt;private/internal APIs&lt;/strong&gt; that &lt;strong&gt;don’t need&lt;/strong&gt; all the features provided by an OAuth Server.&lt;/p&gt;

&lt;p&gt;In this part, I will use &lt;a href="https://iankumu.com/blog/laravel-sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt; to create a simple authentication service for my API. I will use the default email and password to authenticate a user.&lt;/p&gt;

&lt;p&gt;To learn more about the two authentication packages, you can read the &lt;a href="https://iankumu.com/blog/laravel-sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt; article or the &lt;a href="https://iankumu.com/blog/laravel-passport" rel="noopener noreferrer"&gt;Laravel Passport&lt;/a&gt; article.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration and Setup
&lt;/h4&gt;

&lt;p&gt;We will first create an authentication scaffold using &lt;strong&gt;Laravel Breeze&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/breeze &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then install the package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan breeze:install
php artisan migrate
npm &lt;span class="nb"&gt;install 
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create &lt;strong&gt;a basic authentication scaffold&lt;/strong&gt; and a &lt;strong&gt;forgot and reset password&lt;/strong&gt; functionality out of the box.&lt;/p&gt;

&lt;p&gt;Let’s now &lt;strong&gt;install Laravel sanctum&lt;/strong&gt; and set it up&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/sanctum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is to &lt;strong&gt;publish Sanctum’s configurations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Finally, we can migrate the database that will store the access tokens&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last step is to &lt;strong&gt;allow Sanctum to issue access tokens&lt;/strong&gt; which will be used to authenticate users’ requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;App/Models/User
&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\Models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// use Illuminate\Contracts\Auth\MustVerifyEmail;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Factories\HasFactory&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\Auth\User&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Authenticatable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Notifications\Notifiable&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;Laravel\Sanctum\HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//import the trait&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;Authenticatable&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;HasApiTokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//add this trait&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Notifiable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * The attributes that are mass assignable.
     *
     * @var array&amp;lt;int, string&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * The attributes that should be hidden for serialization.
     *
     * @var array&amp;lt;int, string&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$hidden&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'remember_token'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * The attributes that should be cast.
     *
     * @var array&amp;lt;string, string&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$casts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'email_verified_at'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'datetime'&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;We can now create a new controller that will be responsible for the Authentication&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Register
&lt;/h4&gt;

&lt;p&gt;We can start by fleshing out the &lt;strong&gt;user registration logic&lt;/strong&gt;. We will use the default user table that comes with laravel but feel free to add and remove some columns as you please&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Auth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Hash&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;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strtolower&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;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&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;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth_token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;'User Account Created Successfully'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'access_token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'token_type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Bearer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;201&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;From the code, we can see that &lt;strong&gt;a user account is created&lt;/strong&gt; in the database and &lt;strong&gt;an access token is issued to the user&lt;/strong&gt; and is returned back to the user as a response.&lt;/p&gt;

&lt;h4&gt;
  
  
  Login
&lt;/h4&gt;

&lt;p&gt;The next important feature is to &lt;strong&gt;allow users to log in&lt;/strong&gt;. We can add the following logic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Auth&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;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strtolower&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;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password&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="nc"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$credentials&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;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;'Invalid login credentials'&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&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;firstOrFail&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;createToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth_token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;plainTextToken&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;'access_token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'token_type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Bearer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="mi"&gt;200&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;Similar to the registration, we need to &lt;strong&gt;return the access token as soon&lt;/strong&gt; as the user credentials have been validated.&lt;/p&gt;

&lt;p&gt;If the credentials are wrong, we need to alert the user that their credentials are wrong. But how?🤔&lt;/p&gt;

&lt;p&gt;Since a REST API is &lt;strong&gt;stateless, there is no way of flashing responses in real-time&lt;/strong&gt;. We, therefore, need to &lt;strong&gt;return a valid response code and a descriptive message&lt;/strong&gt; so that a user knows what happened at the server level.&lt;/p&gt;

&lt;p&gt;We can use a simple if else statement but this might make our code less clean. A solution is to use the &lt;strong&gt;default Exception Handler&lt;/strong&gt; provided by Laravel.&lt;/p&gt;

&lt;p&gt;We can add some logic &lt;strong&gt;to apply to the whole API&lt;/strong&gt; and catch any Authentication Exceptions and return back a valid API Response back to the client.&lt;/p&gt;

&lt;p&gt;We can update the &lt;strong&gt;App/Exceptions/Handler&lt;/strong&gt;. &lt;strong&gt;php&lt;/strong&gt; to resemble the one below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;App/Exceptions/Handler

&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\Exceptions&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\Auth\AuthenticationException&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\Exceptions\Handler&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;ExceptionHandler&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\Http\Request&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;Throwable&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;Handler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ExceptionHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * A list of exception types with their corresponding custom log levels.
     *
     * @var array&amp;lt;class-string&amp;lt;\Throwable&amp;gt;, \Psr\Log\LogLevel::*&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$levels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * A list of the exception types that are not reported.
     *
     * @var array&amp;lt;int, class-string&amp;lt;\Throwable&amp;gt;&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$dontReport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * A list of the inputs that are never flashed to the session on validation exceptions.
     *
     * @var array&amp;lt;int, string&amp;gt;
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$dontFlash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'current_password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password_confirmation'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Register the exception handling callbacks for the application.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;register&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="nf"&gt;renderable&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;AuthenticationException&lt;/span&gt; &lt;span class="nv"&gt;$exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'api/*'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$exception&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationException&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;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;expectsJson&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt;
                        &lt;span class="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;'Unauthenticated.'&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="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="s1"&gt;'Description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Missing or Invalid Access Token'&lt;/span&gt;
                        &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="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;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This will come in handy when we discuss &lt;strong&gt;middleware&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Logout
&lt;/h4&gt;

&lt;p&gt;Of course in each system, &lt;strong&gt;we need a logout functionality&lt;/strong&gt; so we will also create its function&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;logout&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&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;'Succesfully Logged out'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;200&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;Note that we are using the delete function to &lt;strong&gt;invalidate an existing access token and delete&lt;/strong&gt; it from the database. This makes the access token unusable and we can comfortably say the user is logged out.&lt;/p&gt;

&lt;p&gt;The final piece left is to create the endpoints/routes in the &lt;strong&gt;routes/api.php&lt;/strong&gt; 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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'login'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'register'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'logout'&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only the logout endpoint &lt;strong&gt;needs middleware&lt;/strong&gt; because it requires a token to be passed to v &lt;strong&gt;erify which user is being logged out&lt;/strong&gt; of the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scopes and Middlewares
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/9.x/sanctum#token-abilities" rel="noopener noreferrer"&gt;Scopes&lt;/a&gt; are commonly used in APIs to &lt;strong&gt;assign abilities to tokens&lt;/strong&gt;. They help flesh out &lt;strong&gt;what a user can and cannot do in a system&lt;/strong&gt;. Think of them as &lt;strong&gt;permissions you grant to users&lt;/strong&gt; once you onboard them. Some users can access financial records in a system while others cannot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/9.x/sanctum#token-ability-middleware" rel="noopener noreferrer"&gt;Middlewares&lt;/a&gt; on the other hand are &lt;strong&gt;used to protect endpoints from unauthorized access&lt;/strong&gt;. Think of them as &lt;strong&gt;a gate that filters out valid requests from unauthorized and malicious requests&lt;/strong&gt;. They help &lt;strong&gt;safeguard your endpoints&lt;/strong&gt; from being accessed by users who have no role in accessing them.&lt;/p&gt;

&lt;p&gt;We can add the &lt;strong&gt;auth:sanctum&lt;/strong&gt; middleware to the product’s endpoints to safeguard them. This means that for a request to be considered valid, it has to have the &lt;strong&gt;Authorization: Bearer token&lt;/strong&gt; headers(where the token is the actual access token issued by the API).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HEADERS {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer &amp;lt;Token&amp;gt;'
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each request &lt;strong&gt;has to include the bearer token&lt;/strong&gt; in the headers or the server will respond with a 401(Unauthorized) response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grouping Endpoints
&lt;/h3&gt;

&lt;p&gt;In most cases, you might have &lt;strong&gt;multiple endpoints that share&lt;/strong&gt; some common things such as &lt;strong&gt;version&lt;/strong&gt; (e.g v1,v2), &lt;strong&gt;prefixes&lt;/strong&gt; (admin), or &lt;strong&gt;middleware&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is important to &lt;strong&gt;always version your APIs&lt;/strong&gt; especially if they are being used by the public. This helps in &lt;strong&gt;preventing breaking changes&lt;/strong&gt; and also &lt;strong&gt;allows for backward compatibility&lt;/strong&gt; in the event new APIs are available.&lt;/p&gt;

&lt;p&gt;We can group these endpoints using the &lt;strong&gt;Route::group&lt;/strong&gt; method&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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'middleware'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//All Routes that share the auth:sanctum middleware&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we can have our code organized and clean. In this example, I will group the routes to be of &lt;strong&gt;version 1&lt;/strong&gt; and use the &lt;strong&gt;auth:sanctum&lt;/strong&gt; middleware.&lt;/p&gt;

&lt;p&gt;We might also want to &lt;strong&gt;reduce the size&lt;/strong&gt; of the &lt;strong&gt;api.php&lt;/strong&gt; file by making each resource use &lt;strong&gt;apiresource.&lt;/strong&gt; This simple function reduces the file size by almost 60% and makes reading and maintaining the code an easy task.&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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;apiResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ProductsController&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;apiresource method&lt;/strong&gt; under the hood works by mapping the main functions(index, show, store, update and delete) in our controller to their various endpoints.&lt;/p&gt;

&lt;p&gt;For example &lt;strong&gt;products.show&lt;/strong&gt; is mapped to the endpoint &lt;strong&gt;api/products/{product}.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are some &lt;strong&gt;cool techniques&lt;/strong&gt; you can use to optimize your development experience and become more productive when developing your APIs.&lt;/p&gt;

&lt;p&gt;The final &lt;strong&gt;routes/api.php&lt;/strong&gt; file should resemble the one below&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\ProductsController&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\Http\Controllers\UserAuthenticationController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/&lt;/span&gt;

&lt;span class="c1"&gt;//These routes are NOT protected using middleware&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'v1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'login'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'login'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'register'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'register'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//These routes are protected using middleware&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'v1'&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'logout'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserAuthenticationController&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;'logout'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;apiResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ProductsController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing using Postman
&lt;/h3&gt;

&lt;p&gt;The last step in this tutorial is to test our API through an HTTP Client. There are numerous HTTP Clients such as &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; and &lt;a href="https://www.thunderclient.com/" rel="noopener noreferrer"&gt;Thunderclient&lt;/a&gt; just to name a few.&lt;/p&gt;

&lt;p&gt;I personally use &lt;strong&gt;Thunderclient&lt;/strong&gt; because it integrates seamlessly with Vscode which is my goto editor. It can be added as a Vscode extension thereby making your Vscode editor a powerful editor and REST API client at the same time.&lt;/p&gt;

&lt;p&gt;It improves my productivity and development experience immensely. You are free to use any other HTTP Client of your choice.&lt;/p&gt;

&lt;p&gt;I will use postman in this article as most people are familiar with it.&lt;/p&gt;

&lt;p&gt;We will break down the test from &lt;strong&gt;authentication&lt;/strong&gt; to the &lt;strong&gt;basic CRUD&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Authentication
&lt;/h4&gt;

&lt;p&gt;We can further break down authentication into registration, login and logout.&lt;/p&gt;

&lt;h5&gt;
  
  
  Registration
&lt;/h5&gt;

&lt;p&gt;We can make a POST request to the endpoint &lt;strong&gt;api/v1/register&lt;/strong&gt; with the body on postman&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FRegister-1024x579.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FRegister-1024x579.jpg" alt="Laravel REST APIs(register)"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Successful Registration&lt;/em&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Login
&lt;/h5&gt;

&lt;p&gt;To test login functionality, we can make a POST request to the &lt;strong&gt;api/v1/login&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FFailed-Login-1024x541.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FFailed-Login-1024x541.jpg" alt="Laravel REST APIs(login)"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Failed Login&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A failed login attempt returns a 401(Unauthorized) Status Code and also returns a descriptive message to the client&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FSuccessful-Login-1024x576.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FSuccessful-Login-1024x576.jpg" alt="Laravel REST APIs(login)"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Successful Login&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A successful login attempt returns a 200(OK) Status Code and also returns an access token that can be stored for future use.&lt;/p&gt;

&lt;h5&gt;
  
  
  Logout
&lt;/h5&gt;

&lt;p&gt;Logout can be tested by making a POST request to the api/v1/logout endpoint. We also need to attach the bearer token assigned to us during registration/login to the Headers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FSuccessful-Logout-1024x540.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FSuccessful-Logout-1024x540.jpg" alt="Laravel REST APIs(logout)"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Logout&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Upon success, a descriptive message and a 200(OK) Status Code are returned back to a User.&lt;/p&gt;

&lt;p&gt;We can now test the &lt;strong&gt;Product resource&lt;/strong&gt;. Similar to log out, we also need to attach the bearer token assigned to us during registration/login to the Headers. This is because all the product’s endpoints are protected by the &lt;strong&gt;auth:sanctum&lt;/strong&gt; middleware.&lt;/p&gt;

&lt;p&gt;If we try to access any product’s endpoint &lt;strong&gt;without the access token&lt;/strong&gt; , the server will respond with a 401(Unauthorized) Status Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FUnauthorized-Access-1024x588.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FUnauthorized-Access-1024x588.jpg" alt="Unauthorized Access"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Unauthorized Access&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is because we registered an Exception Handler to catch any access to the API that is not authorized and return a 401 Status Code with a descriptive response. This protects our API endpoints from unauthorized access.&lt;/p&gt;

&lt;h4&gt;
  
  
  Get All Products
&lt;/h4&gt;

&lt;p&gt;All products can be returned by making a &lt;strong&gt;GET&lt;/strong&gt; request to the &lt;strong&gt;api/v1/products&lt;/strong&gt; endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FGet-All-Products-1024x628.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FGet-All-Products-1024x628.jpg" alt="Get all products REST API"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Get All Products&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Get A Single Product
&lt;/h4&gt;

&lt;p&gt;We can fetch a single product from the API by making a &lt;strong&gt;GET&lt;/strong&gt; request to the &lt;strong&gt;api/v1/products/{id}&lt;/strong&gt; endpoint&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FGet-a-Single-Product-1024x660.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FGet-a-Single-Product-1024x660.jpg" alt="Get a single product REST API"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Get a Single Product&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Add A Product
&lt;/h4&gt;

&lt;p&gt;We can add a product by making a &lt;strong&gt;POST&lt;/strong&gt; request to the &lt;strong&gt;api/v1/products&lt;/strong&gt; endpoint&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FAdd-a-Product-1024x659.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FAdd-a-Product-1024x659.jpg" alt="Add a Product REST API"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Add a Product&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Update A Product
&lt;/h4&gt;

&lt;p&gt;To update a product’s details, we can make a &lt;strong&gt;PUT/PATCH&lt;/strong&gt; request to the &lt;strong&gt;api/v1/products/{id}&lt;/strong&gt; endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FUpdate-a-Product-Details-1024x657.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FUpdate-a-Product-Details-1024x657.jpg" alt="Update a Product REST API"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Update a Product&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Delete A Product
&lt;/h4&gt;

&lt;p&gt;We can make a &lt;strong&gt;DELETE&lt;/strong&gt; request to the &lt;strong&gt;api/v1/products/{id}&lt;/strong&gt; endpoint to delete a product from the database&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FDelete-a-Product-1024x519.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F11%2FDelete-a-Product-1024x519.jpg" alt="Delete a Product REST API"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Delete a Product&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing
&lt;/h2&gt;

&lt;p&gt;In this article, we have covered what Rest APIs are and how to create one in Laravel. We have also covered API authentication and Using Middleware to control access to your API. I hope this article was insightful and helped you create a powerful REST API in laravel.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-rest-api/" rel="noopener noreferrer"&gt;How to Build a Rest API with Laravel: A Beginners Guide&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>restapi</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Upload Files/Images to Google Cloud Storage in Laravel</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Mon, 31 Oct 2022 13:14:15 +0000</pubDate>
      <link>https://forem.com/iankumu/how-to-upload-filesimages-to-google-cloud-storage-in-laravel-4nf3</link>
      <guid>https://forem.com/iankumu/how-to-upload-filesimages-to-google-cloud-storage-in-laravel-4nf3</guid>
      <description>&lt;p&gt;Laravel provides a powerful filesystem integration that makes working with Files an easy task. Laravel integrates with &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt; out of the box and you can also use &lt;strong&gt;the default disk space&lt;/strong&gt; on your computer/server to store files.&lt;/p&gt;

&lt;p&gt;The market, however, has seen the rise of other Object Storage services such as &lt;a href="https://cloud.google.com/storage/" rel="noopener noreferrer"&gt;Google Cloud Storage&lt;/a&gt; and &lt;a href="https://azure.microsoft.com/en-us/products/storage/blobs/" rel="noopener noreferrer"&gt;Azure Blob Storage&lt;/a&gt; just to name a few.&lt;/p&gt;

&lt;p&gt;In this article, I will show you &lt;strong&gt;how to upload files/images to Google Cloud Storage.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Object Storage
&lt;/h2&gt;

&lt;p&gt;When it comes to files, it is way easier to just store them on the disk, say for your server, because it is free and it is one way of utilizing your server space assigned to you &lt;a href="https://www.iankumu.com/blog/best-laravel-hosting/" rel="noopener noreferrer"&gt;by your host&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, it does come at risk since the server can always get corrupted and worse get deleted making all your files and images to be lost in the event of such a scenario.&lt;/p&gt;

&lt;p&gt;It is also not scalable because you would have to dedicate one instance to primarily store files which can lead to more revenue spent on your infrastructure.&lt;/p&gt;

&lt;p&gt;It is also not secure because you would need to actively implement security features to safeguard your file server.&lt;/p&gt;

&lt;p&gt;Object Storage help solve these problems as they provide &lt;strong&gt;Security&lt;/strong&gt; , &lt;strong&gt;Scalability&lt;/strong&gt; and &lt;strong&gt;Availability&lt;/strong&gt; at the fraction of the price.&lt;/p&gt;

&lt;p&gt;Take Google Cloud for instance, for just 0.02$, at the time of writing, you get 1GB of storage. This provides all the features I mentioned above and removes the burden of maintaining your own File Server. Just connect to their API and you are good to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Upload Files to Google Cloud Storage in Laravel
&lt;/h2&gt;

&lt;p&gt;To &lt;a href="https://www.iankumu.com/blog/laravel-file-upload/" rel="noopener noreferrer"&gt;Upload Files&lt;/a&gt; to Google Cloud Storage, you can follow the following steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Service Account
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://cloud.google.com/iam/docs/understanding-service-accounts/" rel="noopener noreferrer"&gt;Service Account&lt;/a&gt; allows a system to authenticate itself when accessing Data from Google APIs. Access to Google is granted based on the IAM and is specified in the service account. This makes it easy for us to specify which services our Application will have access to.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In your Google Cloud Console, head over to the &lt;a href="https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts" rel="noopener noreferrer"&gt;Service Accounts&lt;/a&gt; Section &lt;/li&gt;
&lt;li&gt;Select your project and Create a Service Account. &lt;/li&gt;
&lt;li&gt;Once the Service account is created, you will be assigned &lt;strong&gt;a random email address&lt;/strong&gt; for your service account &lt;/li&gt;
&lt;li&gt;The next step is to &lt;strong&gt;create a Key&lt;/strong&gt; which you will use in our Laravel Application. &lt;/li&gt;
&lt;li&gt;In the keys tab in your newly created service account, click on the &lt;strong&gt;add key button&lt;/strong&gt; and choose the JSON option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fword-image-2396-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fword-image-2396-1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will create a new key with its corresponding service account JSON file which you can download to your local pc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a Storage Bucket
&lt;/h3&gt;

&lt;p&gt;Once you are done with setting up the Service Account, it is now time to create a Storage Bucket. A bucket is &lt;strong&gt;a basic container which holds all your data&lt;/strong&gt;. You can have folders and files in a single Bucket.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to the &lt;a href="https://console.cloud.google.com/storage/browser" rel="noopener noreferrer"&gt;Cloud Storage&lt;/a&gt; Tab and create a new Bucket &lt;/li&gt;
&lt;li&gt;Name your bucket and &lt;strong&gt;choose the location where your bucket will be created&lt;/strong&gt;. In this part, I will just choose a &lt;strong&gt;single region&lt;/strong&gt; as it is the cheapest &lt;/li&gt;
&lt;li&gt;For the &lt;strong&gt;default storage class&lt;/strong&gt; , just choose the &lt;strong&gt;Standard&lt;/strong&gt; class, or any other class depending on your needs &lt;/li&gt;
&lt;li&gt;When it comes to &lt;strong&gt;how your data will be accessed&lt;/strong&gt; , there are two options; &lt;strong&gt;Uniform&lt;/strong&gt; and &lt;strong&gt;Fine-grained&lt;/strong&gt;. Google Recommends Uniform Access Control but I was not able to wrap my head around how it works and thus I just use &lt;strong&gt;Fine-grained&lt;/strong&gt; access control which allows me to authenticate through the service account I created earlier. &lt;/li&gt;
&lt;li&gt;The last step is to choose the &lt;strong&gt;protection tools&lt;/strong&gt;. You can leave it as &lt;strong&gt;None&lt;/strong&gt; since Google Cloud Storage Buckets are Secure by default. Once done click Create and your bucket is now ready. &lt;/li&gt;
&lt;li&gt;One final thing you need to do is to grant your service account access to your bucket and specify its roles. Click on your &lt;strong&gt;new bucket&lt;/strong&gt; and head to the &lt;strong&gt;permissions&lt;/strong&gt; tab. &lt;/li&gt;
&lt;li&gt;Click on grant access and Add your Service Account as a Principal(search for it and it should pop up in the search). &lt;/li&gt;
&lt;li&gt;You then need to assign cloud storage roles to your principal. The Roles you should assign are &lt;strong&gt;Storage Admin&lt;/strong&gt; , &lt;strong&gt;Storage Object Admin&lt;/strong&gt; , &lt;strong&gt;Storage Object Creator&lt;/strong&gt; , and &lt;strong&gt;Storage Object Viewer&lt;/strong&gt;. Click save and your bucket is now ready to be used in Laravel. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create a Laravel Project
&lt;/h3&gt;

&lt;p&gt;If you have no Laravel project created yet, you can create one using the &lt;strong&gt;laravel new&lt;/strong&gt; command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

laravel new gcs storage 


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Install package
&lt;/h3&gt;

&lt;p&gt;To interact with Google Cloud Storage APIs, we will use &lt;a href="https://github.com/Superbalist/laravel-google-cloud-storage" rel="noopener noreferrer"&gt;this package&lt;/a&gt; to do so.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

composer require superbalist/laravel-google-cloud-storage


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Update Filesystem file
&lt;/h3&gt;

&lt;p&gt;Laravel handles storage disks through the &lt;strong&gt;config/filesystems.php&lt;/strong&gt; file. The file contains three different disk services, &lt;strong&gt;local&lt;/strong&gt; , &lt;strong&gt;public&lt;/strong&gt; and &lt;strong&gt;s3&lt;/strong&gt;. We need to add gcs to register it as another disk available to our laravel application&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;

&lt;span class="c1"&gt;//config/filesystems.php&lt;/span&gt;

&lt;span class="s1"&gt;'gcs'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'driver'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'gcs'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'project_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_CLOUD_PROJECT_ID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'your-project-id'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'key_file'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_CLOUD_KEY_FILE'&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;'service-account.json'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="c1"&gt;// optional: /path/to/service-account.json&lt;/span&gt;
            &lt;span class="s1"&gt;'bucket'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_CLOUD_STORAGE_BUCKET'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'your-bucket'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'path_prefix'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_CLOUD_STORAGE_PATH_PREFIX'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// optional: /default/path/to/apply/in/bucket&lt;/span&gt;
            &lt;span class="s1"&gt;'storage_api_uri'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'GOOGLE_CLOUD_STORAGE_API_URI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// see: Public URLs below&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The updated &lt;strong&gt;filesystems.php&lt;/strong&gt; file should resemble this one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Ffilesystems-542x1024.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Ffilesystems-542x1024.png" alt="filesystems"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;filesystems config file&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy Service Account JSON file to the base path
&lt;/h3&gt;

&lt;p&gt;The next step is to copy the Service Account JSON file we downloaded earlier to your Laravel Application base path. If you have not downloaded it yet, refer to this section to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fimage-2.png" alt="Service Account JSON File"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Service Account JSON File&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Environment Variables
&lt;/h3&gt;

&lt;p&gt;You need to specify the &lt;strong&gt;bucket name&lt;/strong&gt; and the &lt;strong&gt;project id&lt;/strong&gt;. You can find your project id in the &lt;a href="https://console.cloud.google.com/home/dashboard" rel="noopener noreferrer"&gt;console dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fenv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fenv.png" alt="Google Cloud Storage envs"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Google Cloud Storage Environment Variables&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You also need to update the &lt;strong&gt;Filesystem Driver&lt;/strong&gt; to &lt;strong&gt;gcs&lt;/strong&gt; in the &lt;strong&gt;.env file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fgcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fgcs.png" alt="Filesystem variable"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Filesystem variable&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload Files
&lt;/h3&gt;

&lt;p&gt;You can now interact with google cloud storage through Laravel. To Upload files, I will create a new Files Controller&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

php artisan make:controller FilesController  


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

&lt;/div&gt;

&lt;p&gt;I will create an Upload File Function that will take care of Uploading Files to Google Cloud Storage.&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Str&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\Http\UploadedFile&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;uploadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UploadedFile&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;storeAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nv"&gt;$folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getClientOriginalExtension&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'gcs'&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;You can then request files through HTTP and Upload them to Google Cloud.&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;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;uploadFile&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="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Categories'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$category&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;Categories&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;back&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;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fimage-1-1024x406.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F10%2Fimage-1-1024x406.png" alt="Google Cloud Storage"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Google Cloud Storage&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieve Files/Images.
&lt;/h3&gt;

&lt;p&gt;You can retrieve files using the &lt;strong&gt;Storage&lt;/strong&gt; Facade. If you are storing the file path in the database, you can append the path to the URL method.&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gcs'&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;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This will return the file URL in this pattern.&lt;/p&gt;

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

http://storage.googleapis.com/bucket-name/folder/your_file.png 


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

&lt;/div&gt;

&lt;p&gt;If you prefer to use &lt;strong&gt;your own custom domain name&lt;/strong&gt; , you can add a &lt;strong&gt;CNAME&lt;/strong&gt; to your DNS records.&lt;/p&gt;

&lt;p&gt;You can read &lt;a href="https://cloud.google.com/storage/docs/request-endpoints#cname" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; for further instructions on how to use your custom domain name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete Files.
&lt;/h3&gt;

&lt;p&gt;I will also add another function that will be responsible for deleting files from Google Cloud Storage if they are not needed anymore.&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Storage&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;deleteFile&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gcs'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&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;You can now delete files by calling the function and passing the File Path as a parameter.&lt;/p&gt;

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

&lt;p&gt;In this guide, we have learnt how to set up and upload files to Google Cloud Storage and how to Manage those files by Retrieving and Deleting them. I hope this article was insightful and helpful. You can read some of the &lt;a href="https://www.iankumu.com/blog/laravel-file-upload/" rel="noopener noreferrer"&gt;best practices for uploading Files in Laravel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-google-cloud-storage/" rel="noopener noreferrer"&gt;How to Upload Files/Images to Google Cloud Storage in Laravel&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>gcp</category>
      <category>cloud</category>
      <category>s3</category>
    </item>
    <item>
      <title>How to Build a Live Search using Laravel, Livewire, and Meilisearch</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Fri, 14 Oct 2022 18:35:47 +0000</pubDate>
      <link>https://forem.com/iankumu/how-to-build-a-live-search-using-laravel-livewire-and-meilisearch-4kcp</link>
      <guid>https://forem.com/iankumu/how-to-build-a-live-search-using-laravel-livewire-and-meilisearch-4kcp</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IZ-2V7Gv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnz0yescfxri5ldzelmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IZ-2V7Gv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnz0yescfxri5ldzelmn.png" alt="Laravel Search" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most powerful features of Laravel is its ability to integrate with many different services. By default, Laravel integrates with the &lt;a href="https://www.meilisearch.com/"&gt;Meilisearch service&lt;/a&gt;. This allows you to easily query your data using the Laravel Eloquent ORM. But what if you want to build a custom search page? Well, it’s easy to do with a couple of tweaks. This article will show you how to create a custom search page using &lt;a href="https://laravel.com/"&gt;Laravel&lt;/a&gt;, &lt;a href="https://laravel-livewire.com/"&gt;Livewire&lt;/a&gt;, and &lt;a href="https://www.meilisearch.com/"&gt;Meilisearch&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.meilisearch.com/"&gt;Meilisearch&lt;/a&gt; is an open-source search engine that is built using Rust and can be integrated into any application to provide Full-Text Search. It comes with a lot of features that we can use to our advantage as developers. Because it is built using Rust, it is &lt;strong&gt;blazing fast&lt;/strong&gt; making it a useful utility for any application. Laravel, through &lt;strong&gt;Laravel Scout&lt;/strong&gt; , comes with an already implemented solution for meilisearch making it easy to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  But What is Laravel Scout?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/9.x/scout"&gt;Laravel Scout&lt;/a&gt; is a first-party Package developed by Taylor Otwell that can be used to &lt;strong&gt;add Full-Text Search to your Eloquent Models&lt;/strong&gt;. It makes it easy to search through your Eloquent Models and return the search results in a clean fashion.&lt;/p&gt;

&lt;p&gt;Let’s get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to integrate Full-Text Search into Laravel
&lt;/h2&gt;

&lt;p&gt;Before we start, we need a couple of things;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Laravel Application &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.meilisearch.com/learn/getting_started/quick_start.html"&gt;Meilisearch Installed&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have created a new Laravel Application and downloaded and installed Meilisearch, you can now follow these steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Laravel Breeze
&lt;/h3&gt;

&lt;p&gt;If you have created a new Laravel Application, you can install a &lt;a href="https://laravel.com/docs/9.x/starter-kits"&gt;starter kit&lt;/a&gt;. I will install Laravel breeze in this tutorial.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/breeze 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prepare Model and Migration
&lt;/h3&gt;

&lt;p&gt;We now need a Model to work with. I am going to use an &lt;strong&gt;Article Model&lt;/strong&gt; which will contain an article name, author name and article content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Articles &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create an Article Model and its corresponding 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;//App/Models/Articles.php
&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\Models&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\Database\Eloquent\Factories\HasFactory&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\Database\Eloquent\Model&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;Articles&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&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;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;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&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\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Run the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&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;'articles'&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;'name'&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;longText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'content'&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;'author'&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;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Reverse the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'articles'&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;h3&gt;
  
  
  Seed the Database
&lt;/h3&gt;

&lt;p&gt;When testing, I usually use Factories and Seeders to speed up my development process. To do so, we can create an &lt;strong&gt;Article Factory&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We can use faker to seed the database and then register the factory in the Database seeder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//database/factories/ArticlesFactory.php
&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;Database\Factories&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\Database\Eloquent\Factories\Factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory&amp;lt;\App\Models\Articles&amp;gt;
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticlesFactory&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Define the model's default state.
     *
     * @return array&amp;lt;string, mixed&amp;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;definition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'author'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;faker&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;//database/seeders/DatabaseSeeder.php&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="n"&gt;php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Database\Seeders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// use Illuminate\Database\Console\Seeds\WithoutModelEvents;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Articles&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\Database\Seeder&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;DatabaseSeeder&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Seeder&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Seed the application's database.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Articles&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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="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;To seed the database, &lt;strong&gt;db:seed&lt;/strong&gt; command will be of help&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan db:seed 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install and Configure Livewire
&lt;/h3&gt;

&lt;p&gt;The next step is to install the &lt;a href="https://github.com/livewire/livewire"&gt;livewire package&lt;/a&gt;. Livewire will be a major help in adding reactivity to our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require livewire/livewire
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then need to include the livewire Javascripts in the &lt;strong&gt;app.blade.php&lt;/strong&gt; file in the &lt;strong&gt;resources/views/components&lt;/strong&gt; folder.&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="mf"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;livewireStyles&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="mf"&gt;...&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;livewireScripts&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create Article Component
&lt;/h3&gt;

&lt;p&gt;Livewire helps us scaffold components fast using the &lt;strong&gt;make:livewire&lt;/strong&gt; command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This creates a Component which we can reuse in multiple places.&lt;/p&gt;

&lt;p&gt;This command creates two files, one in the &lt;strong&gt;App/Http/Livewire&lt;/strong&gt; Folder and another one in the &lt;strong&gt;resources/views/livewire&lt;/strong&gt; folder. These two will be essential in creating our full-text search&lt;/p&gt;

&lt;p&gt;Through laravel breeze, Laravel scaffolded authentication and a dashboard which we can now use to display the Articles.&lt;/p&gt;

&lt;p&gt;We can fetch records from the database and display them using the Articles Component.&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="p"&gt;{{&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dashboard&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;blade&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"header"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;h2&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"font-semibold text-xl text-gray-800 leading-tight"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Dashboard'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"py-12"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"max-w-7xl mx-auto sm:px-6 lg:px-8"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bg-white overflow-hidden shadow-sm sm:rounded-lg"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"p-6 bg-white border-b border-gray-200"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                   &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;livewire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'articles'&lt;/span&gt;&lt;span class="p"&gt;){{&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nc"&gt;Including&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nc"&gt;Article&lt;/span&gt; &lt;span class="nc"&gt;Compontent&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
                &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install and Set up Laravel Scout
&lt;/h3&gt;

&lt;p&gt;The next step is to install the Laravel scout package using composer&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We can then publish the configurations&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Laravel Scout allows us to use any search driver such as &lt;strong&gt;database&lt;/strong&gt; , &lt;strong&gt;algolia&lt;/strong&gt; or &lt;strong&gt;meilisearch&lt;/strong&gt; etc Meilisearch is a popular search engine because it is open source and can be self-hosted. It makes search easy because it handles all the technical bits such as &lt;strong&gt;typos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Laravel Scout helps with all the other factors in search including &lt;strong&gt;indexing&lt;/strong&gt; , &lt;strong&gt;updating the index&lt;/strong&gt; and &lt;strong&gt;returning the results&lt;/strong&gt; in a Laravel Friendly way. Under the hood, Scout uses &lt;a href="https://laravel.com/docs/9.x/eloquent#observers"&gt;Model Observers&lt;/a&gt; to update the records and &lt;strong&gt;re-index&lt;/strong&gt; the search results in Meilisearch.&lt;/p&gt;

&lt;p&gt;To set up Scout in our Models, we will need to include the &lt;strong&gt;Searchable trai&lt;/strong&gt; t in our Model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Models/Articles.php
&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\Models&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\Database\Eloquent\Factories\HasFactory&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\Database\Eloquent\Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Scout\Searchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//import the trait&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Articles&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Searchable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//add this trait&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&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;We also need to install a few packages to be able to interact with meilisearch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then set the environment variables to now use Meilisearch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add Search Logic
&lt;/h3&gt;

&lt;p&gt;Before performing a Search, we need to index our records in meilisearch using the &lt;strong&gt;scout:import&lt;/strong&gt; command&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, we can use Eloquent to perform a search on our records&lt;/p&gt;

&lt;p&gt;We can update our Livewire Component to include the Search Logic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;//App/Livewire/Articles.php
&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\Http\Livewire&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\Articles&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;ModelsArticles&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;Livewire\Component&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;Articles&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$search&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$articles&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;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;empty&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;search&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;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModelsArticles&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;articles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ModelsArticles&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'livewire.articles'&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;h3&gt;
  
  
  Add Search Input Field
&lt;/h3&gt;

&lt;p&gt;On the Articles Table, we can add a search input field that will receive the query and send it to the backend.&lt;/p&gt;

&lt;p&gt;Livewire provides a cool way to perform &lt;strong&gt;data binding&lt;/strong&gt; which we can use to our advantage. Using the &lt;strong&gt;wire:model&lt;/strong&gt; property, we can pass the query onto the server and get the results back synchronously.&lt;/p&gt;

&lt;p&gt;We can use one of the &lt;a href="https://tailwindcomponents.com/"&gt;tailwind components&lt;/a&gt; templates to scaffold a view.&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="c"&gt;&amp;lt;!-- resources/view/livewire/articles.blade.php --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
     &lt;span class="c"&gt;&amp;lt;!-- component --&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://demos.creative-tim.com/notus-js/assets/styles/tailwind.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://demos.creative-tim.com/notus-js/assets/vendor/@fortawesome/fontawesome-free/css/all.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

       &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"py-1 bg-blueGray-50"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full xl:w-8/12 mb-12 xl:mb-0 px-4 mx-auto mt-24"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative flex flex-col min-w-0 break-words bg-white w-full mb-6 shadow-lg rounded "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rounded-t mb-0 px-4 py-3 border-0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-wrap items-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative w-full px-4 max-w-full flex-grow flex-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-semibold text-base text-blueGray-700"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Articles&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"relative w-full px-4 max-w-full flex-grow flex-1 text-right"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&lt;/span&gt; &lt;span class="na"&gt;wire:model=&lt;/span&gt;&lt;span class="s"&gt;"search"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

               &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"block w-full overflow-x-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"items-center bg-transparent w-full border-collapse "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
                       &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                   Article name
                        &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                   Content
                    &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-6 bg-blueGray-50 text-blueGray-500 align-middle border border-solid border-blueGray-100 py-3 text-xs uppercase border-l-0 border-r-0 whitespace-nowrap font-semibold text-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                   Author
                    &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                   &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;

                   &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
                        @if (!$articles-&amp;gt;isEmpty())
                            @foreach ($articles as $article)

                                &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
                                    &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border-t-0 px-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap p-4 text-left text-blueGray-700 "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                    {{$article-&amp;gt;name}}
                                    &lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
                                    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border-t-0 px-6 align-middle border-l-0 border-r-0 text-xs whitespace-nowrap p-4 "&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                        {{$article-&amp;gt;content}}
                                    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                                    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border-t-0 px-6 align-center border-l-0 border-r-0 text-xs whitespace-nowrap p-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                                        {{$article-&amp;gt;author}}
                                    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                                &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
                            @endforeach
                        @else
                            &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"border-t-0 px-6 align-center border-l-0 border-r-0 text-xs whitespace-nowrap p-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            No Results Found
                            &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
                        @endif
                   &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;

               &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

       &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Livewire handles getting the query from the input field, makes an ajax request to the backend and returns the results back to the frontend.&lt;/p&gt;

&lt;p&gt;This makes it easy to create a live search with minimal effort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xnfQPoyX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/10/Laravel-Search.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xnfQPoyX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/10/Laravel-Search.gif" alt="" width="880" height="366"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Live Search&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Display Results
&lt;/h3&gt;

&lt;p&gt;Once Scout returns the results, Livewire takes care of displaying them on the table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rhyQYhuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/10/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rhyQYhuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/10/image.png" alt="Laravel Search" width="880" height="347"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Searched Results&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;In this article, we have covered how to create a live search using Laravel Livewire and Meilisearch. We covered how to set up your application and include all the features needed for Full-Text Search. I hope this article was insightful. &lt;/p&gt;

&lt;p&gt;If you enjoyed this article, you'd love the &lt;a href="https://www.iankumu.com/blog/newsletter/"&gt;Free Laravel Guide&lt;/a&gt; I prepared for you. Be sure to get your guide today.&lt;br&gt;
Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-search/"&gt;How to Build a Live Search using Laravel, Livewire, and Meilisearch&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>meilisearch</category>
      <category>webdev</category>
      <category>livewire</category>
    </item>
    <item>
      <title>Laravel Mail: How to Send Emails Easily in Laravel</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Fri, 09 Sep 2022 20:21:20 +0000</pubDate>
      <link>https://forem.com/iankumu/laravel-mail-how-to-send-emails-easily-in-laravel-35jc</link>
      <guid>https://forem.com/iankumu/laravel-mail-how-to-send-emails-easily-in-laravel-35jc</guid>
      <description>&lt;p&gt;Sending an email is one of the most important additions to any system; be it Transactional emails or sending newsletter emails. In recent surveys, &lt;a href="https://www.campaignmonitor.com/resources/guides/the-state-of-small-business-marketing/" rel="noopener noreferrer"&gt;64% of small businesses&lt;/a&gt; use emails to reach customers. This makes it necessary to send emails to customers in order to engage your customers and also build a loyal customer base.&lt;/p&gt;

&lt;p&gt;Laravel provides a clean and easy way to send emails without any hassle and difficulties using the &lt;strong&gt;Mailable Class&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I am going to show you &lt;strong&gt;how to easily send emails in Laravel&lt;/strong&gt; and &lt;strong&gt;how to create email templates using markdown&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need to know about Laravel Mail
&lt;/h2&gt;

&lt;p&gt;If you want to send emails from your Laravel application, you need to know about the Laravel Mail API. This simple API is built on top of the popular &lt;a href="https://swiftmailer.symfony.com/" rel="noopener noreferrer"&gt;Swiftmailer library&lt;/a&gt;. You can configure it to use &lt;strong&gt;SMTP&lt;/strong&gt; , &lt;strong&gt;Mailgun&lt;/strong&gt; , &lt;strong&gt;Postmark&lt;/strong&gt; , &lt;strong&gt;Amazon SES&lt;/strong&gt; , or &lt;strong&gt;Sendmail&lt;/strong&gt;. You can also use the simple API to send emails directly from your PHP code. Laravel provides multiple mail drivers for sending emails making it easy to send emails using any integration of your liking.&lt;/p&gt;

&lt;p&gt;The Laravel Mail API makes it easy to &lt;strong&gt;send beautiful email templates&lt;/strong&gt;. You can create a &lt;strong&gt;Mailable class&lt;/strong&gt; and a public function &lt;strong&gt;build()&lt;/strong&gt; that returns your email template.&lt;/p&gt;

&lt;p&gt;It’s easy to get started with Laravel Mail. Just configure your SMTP settings and you’re ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you send Emails in Laravel?
&lt;/h2&gt;

&lt;p&gt;To send an email message in Laravel, you can follow the following steps&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Laravel
&lt;/h3&gt;

&lt;p&gt;You can create a new Laravel project using the &lt;strong&gt;laravel new&lt;/strong&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;laravel new &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create a Mailable Class
&lt;/h3&gt;

&lt;p&gt;You can use the &lt;strong&gt;make:mail&lt;/strong&gt; artisan command in Laravel. This will scaffold a Mailable class which has a &lt;strong&gt;build()&lt;/strong&gt; function where your mail logic will be added.&lt;/p&gt;

&lt;p&gt;You can specify the &lt;strong&gt;email subject&lt;/strong&gt; , and &lt;strong&gt;the content of the email such as images&lt;/strong&gt; , &lt;strong&gt;attachments, and reply to address&lt;/strong&gt; among others.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command will create a Mailable Class in the &lt;strong&gt;app/Mail&lt;/strong&gt; Folder&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\Mail&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\Mail\Mailable&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderMail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Mailable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SerializesModels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create a new message instance.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Build the message.
     *
     * @return $this
     */&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;build&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;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'emails.orders'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Mail Example using Markdown Template
&lt;/h4&gt;

&lt;p&gt;One of the key benefits of laravel is that it &lt;strong&gt;has markdown support&lt;/strong&gt;. You can create an email template using markdown. This allows you to have a boilerplate view of the email which you can customise to your liking or use as is.&lt;/p&gt;

&lt;p&gt;You can modify the &lt;strong&gt;make:mail&lt;/strong&gt; command and add a flag to specify which markdown will be used by your Mailable Class. The markdown template is a blade file that is placed in the “emails” directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:mail OrderMail &lt;span class="nt"&gt;--markdown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;emails.orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a default markdown blade file in the resources/views/emails folder&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="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mail::message'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Introduction&lt;/span&gt;

&lt;span class="nc"&gt;The&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mail::button'&lt;/span&gt;&lt;span class="p"&gt;,&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;''&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="nc"&gt;Text&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;endcomponent&lt;/span&gt;

&lt;span class="nc"&gt;Thanks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;br&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;endcomponent&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using a simple scenario of an order mail, you can pass some default data to the markdown through the &lt;strong&gt;with()&lt;/strong&gt; command in the Mailable Class. You could use the constructor to receive data from other classes.&lt;/p&gt;

&lt;p&gt;You can update the logic of the Mailable class&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Mail&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\Orders&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;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\Mail\Mailable&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="no"&gt;Illuminate\Support\Facades\URL&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;OrderMail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Mailable&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SerializesModels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create a new message instance.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;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="kt"&gt;Orders&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Build the message.
     *
     * @return $this
     */&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;build&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;markdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'emails.orders'&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;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Your Order is being Processed'&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;with&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s1"&gt;'order'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'customer'&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'order_url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'orders.show'&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;order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&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;The next step is to add content to the markdown blade template&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="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mail::message'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Hello&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;$customer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;

&lt;span class="nc"&gt;Your&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="nc"&gt;No&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;been&lt;/span&gt; &lt;span class="n"&gt;placed&lt;/span&gt; &lt;span class="n"&gt;successfully&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="n"&gt;being&lt;/span&gt; &lt;span class="n"&gt;processed&lt;/span&gt;

&lt;span class="nc"&gt;You&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="n"&gt;below&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mail::button'&lt;/span&gt;&lt;span class="p"&gt;,&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="nv"&gt;$order_url&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;endcomponent&lt;/span&gt;

&lt;span class="nc"&gt;Regards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;br&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;endcomponent&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If you want to &lt;a href="https://laravel.com/docs/9.x/mail#customizing-the-components" rel="noopener noreferrer"&gt;customize the Laravel Mail Components&lt;/a&gt;, you can publish the assets and change them to your liking using this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;laravel-mail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Sending email in Laravel
&lt;/h3&gt;

&lt;p&gt;Once you have the email template set, it is now time to send an email. You can use the &lt;strong&gt;Mail Facade&lt;/strong&gt; to send an email. It comes with a lot of methods but the most important is the &lt;strong&gt;to()&lt;/strong&gt; method. This method defines where the email will be sent. You can pass a user’s email as a parameter and Laravel will send the email to the email specified.&lt;/p&gt;

&lt;p&gt;The next important method is the &lt;strong&gt;send()&lt;/strong&gt; method. This method allows us to specify a Mailable message Instance. This is where you specify the Mailable class you had created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Mail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Mail&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;request&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;user&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&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;MailableClass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can update the Facade to include your Mailable Class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Mail&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="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Orders&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="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Mail&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&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;OrderMail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Emails can be &lt;a href="https://www.iankumu.com/blog/laravel-queues/" rel="noopener noreferrer"&gt;queued and sent in the background&lt;/a&gt; making your application even faster.&lt;/p&gt;

&lt;p&gt;Before sending an email,you first need to update the mail configurations.&lt;/p&gt;

&lt;p&gt;You can set the default details in the env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have set the mail configurations, you can now start sending emails from your Laravel Application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Testing emails in Laravel
&lt;/h3&gt;

&lt;p&gt;Laravel makes it easy to test emails using either the &lt;strong&gt;laravel log file&lt;/strong&gt; ,&lt;a href="https://github.com/mailhog/MailHog" rel="noopener noreferrer"&gt;mailhog&lt;/a&gt; or &lt;a href="https://mailtrap.io/" rel="noopener noreferrer"&gt;Mailtrap&lt;/a&gt; as third-party integration. These services provide a &lt;strong&gt;fake SMTP server&lt;/strong&gt; from where you can test and verify that your emails are correctly formatted.&lt;/p&gt;

&lt;p&gt;All you need to do is change the mail configurations in the env file and use the credentials of any fake SMTP server.&lt;/p&gt;

&lt;p&gt;Using Mailtrap for instance, you can visually see how the email is formatted&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-3.png"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sample Email Using Markdown&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Which third-party email sending providers are supported in Laravel?
&lt;/h2&gt;

&lt;p&gt;Laravel supports several third-party email sending providers, including &lt;a href="https://www.mailgun.com/" rel="noopener noreferrer"&gt;Mailgun&lt;/a&gt;, &lt;a href="https://postmarkapp.com/" rel="noopener noreferrer"&gt;Postmark&lt;/a&gt;, &lt;a href="https://aws.amazon.com/ses/" rel="noopener noreferrer"&gt;Amazon SES&lt;/a&gt;, and &lt;a href="https://sendgrid.com/" rel="noopener noreferrer"&gt;SendGrid&lt;/a&gt;. Each provider has its own strengths and weaknesses, so it’s important to choose the one that best suits your needs.&lt;/p&gt;

&lt;p&gt;If you prefer using &lt;strong&gt;your own SMTP server&lt;/strong&gt; , ensure that your server’s SMTP port &lt;strong&gt;is not blocked&lt;/strong&gt;. Most VPS services such as &lt;a href="https://www.iankumu.com/blog/recommends/digital-ocean/" rel="noopener noreferrer"&gt;Digital Ocean&lt;/a&gt; &lt;strong&gt;block port 25(SMTP)&lt;/strong&gt; making it hard to send and receive emails on your server.&lt;/p&gt;

&lt;p&gt;Other services such as &lt;a href="https://www.iankumu.com/blog/recommends/contabo/" rel="noopener noreferrer"&gt;Contabo&lt;/a&gt; and &lt;a href="https://www.iankumu.com/blog/recommends/kamatera/" rel="noopener noreferrer"&gt;Kamatera&lt;/a&gt;, however, &lt;strong&gt;do not block port 25&lt;/strong&gt; making it &lt;strong&gt;easy to host your own mail server.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you prefer hosting your own mail server as opposed to using third-party email service providers, then you can read &lt;a href="https://www.linuxbabe.com/mail-server/setup-basic-postfix-mail-sever-ubuntu" rel="noopener noreferrer"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is good to note that hosting your own mail server comes with its fair share of cons such as &lt;strong&gt;emails&lt;/strong&gt;  &lt;strong&gt;may be delivered to the spam folder&lt;/strong&gt;. This is because your &lt;strong&gt;mail server IP is still new among other email SMTP servers&lt;/strong&gt; and it will require you to &lt;strong&gt;warm up your IP&lt;/strong&gt; so that it gains a good reputation among other servers.&lt;/p&gt;

&lt;p&gt;This is why most people prefer using third-party email service providers so that you concentrate more on what matters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Use Laravel to Send Emails?
&lt;/h2&gt;

&lt;p&gt;One of the great features of Laravel is its &lt;strong&gt;inbuilt mail system&lt;/strong&gt;. This makes it easy to send emails from your application without having to set up a separate mail server. Through its robust Mail API, you can connect to any Email service provider and have your emails sent with ease.&lt;/p&gt;
&lt;h2&gt;
  
  
  Send Emails in Laravel using Gmail’s SMTP Server
&lt;/h2&gt;

&lt;p&gt;Most people prefer using their default Gmail account as an SMTP server for their Laravel Application because &lt;strong&gt;it is free&lt;/strong&gt;. In this part, I will show you how to use Gmail as an SMTP server for sending your Laravel Emails.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure Google Account
&lt;/h3&gt;

&lt;p&gt;You first need to configure some security settings in your Gmail account. To do so, log in to your &lt;a href="https://www.google.com/gmail" rel="noopener noreferrer"&gt;Gmail&lt;/a&gt; account and select “Manage your Google Account” from your profile.&lt;/p&gt;

&lt;p&gt;You then need to &lt;strong&gt;activate 2 step verification&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-4-1024x482.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-4-1024x482.png" alt="Send Emails Laravel with Gmail"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Before 2-step Verification is turned on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you have &lt;strong&gt;activated 2 step verification&lt;/strong&gt; , you will &lt;strong&gt;have&lt;/strong&gt;  &lt;strong&gt;access to the App password section&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-5-1024x480.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-5-1024x480.png" alt="Send Emails Laravel with Gmail"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;After 2-step Verification is turned on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;App passwords section&lt;/strong&gt; and &lt;strong&gt;create a new password&lt;/strong&gt; for your Laravel Mail Application&lt;/p&gt;

&lt;p&gt;Choose the &lt;strong&gt;Mail App&lt;/strong&gt; and the &lt;strong&gt;device Custom&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-6-1024x480.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-6-1024x480.png" alt="Send Emails Laravel with Gmail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-7-1024x481.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-7-1024x481.png" alt="Send Emails Laravel with Gmail"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Generate a New App Password&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Update Mail Configurations
&lt;/h3&gt;

&lt;p&gt;Once you have generated your app password, you can update your mail configurations in the env file to use Gmail’s SMTP configurations&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=youremail@gmail.com
MAIL_PASSWORD=generated password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=youremail@gmail.com
MAIL_FROM_NAME="${APP_NAME}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have set the configurations you are set to send emails using Gmail for free. Do bear in mind that Gmail allows only &lt;strong&gt;500 emails per day&lt;/strong&gt; so if your application will be sending a lot of emails, you might consider other services.&lt;/p&gt;

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

&lt;p&gt;Sending Emails in Laravel is easy and is essential in any production-ready application. Through emails, you can engage customers and also automate some of the tasks that are necessary for a fully functioning application. In this article, we have covered &lt;strong&gt;how to set up a Simple Mail Implementation in Laravel&lt;/strong&gt; and &lt;strong&gt;how to configure Gmail’s SMTP server so that we can use it with our Laravel application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are multiple ways you can further send emails in Laravel. One way is &lt;a href="https://www.iankumu.com/blog/laravel-scheduler/" rel="noopener noreferrer"&gt;scheduling them using Laravel Scheduler&lt;/a&gt;. I hope this article was informative and I hope you enjoyed reading it. &lt;/p&gt;

&lt;p&gt;If you enjoyed this article, you'd love the &lt;a href="https://www.iankumu.com/blog/newsletter/" rel="noopener noreferrer"&gt;Free Laravel Guide&lt;/a&gt; I prepared for you. Be sure to get your guide today.&lt;br&gt;
Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-send-emails/" rel="noopener noreferrer"&gt;Laravel Mail: How to Send Emails Easily in Laravel&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>webdev</category>
      <category>php</category>
      <category>emails</category>
    </item>
    <item>
      <title>Laravel File Upload: A Complete Tutorial and Guide</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Mon, 05 Sep 2022 14:40:28 +0000</pubDate>
      <link>https://forem.com/iankumu/laravel-file-upload-a-complete-tutorial-and-guide-4j8n</link>
      <guid>https://forem.com/iankumu/laravel-file-upload-a-complete-tutorial-and-guide-4j8n</guid>
      <description>&lt;p&gt;Working with files in any application is a crucial part of any system. Laravel provides a filesystem from where we can interact with files; file upload, storing or retrieving them.&lt;/p&gt;

&lt;p&gt;If you have your application &lt;a href="https://www.iankumu.com/blog/how-to-deploy-laravel-on-apache-server/" rel="noopener noreferrer"&gt;deployed to production&lt;/a&gt; using one of the &lt;a href="https://www.iankumu.com/blog/best-laravel-hosting/" rel="noopener noreferrer"&gt;hosting providers&lt;/a&gt;, It is important to know how to manage your resources wisely. One important thing we could do is &lt;strong&gt;compress the files/images&lt;/strong&gt; so that they do not occupy a lot of space in your server or any storage service such as &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt;, &lt;a href="https://cloud.google.com/storage" rel="noopener noreferrer"&gt;Google Cloud Storage&lt;/a&gt; or any other external disk services.&lt;/p&gt;

&lt;p&gt;In this article, I am going to show you &lt;strong&gt;how to upload&lt;/strong&gt; and &lt;a href="https://webtools.iankumu.com/image-compressor" rel="noopener noreferrer"&gt;&lt;strong&gt;compress files&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;in Laravel&lt;/strong&gt; before storing them.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you Upload Files in Laravel?
&lt;/h2&gt;

&lt;p&gt;To upload files in Laravel we can follow the following steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a Laravel Project
&lt;/h3&gt;

&lt;p&gt;We can use the Laravel new command or composer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;laravel new &lt;span class="nb"&gt;test&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project laravel/laravel &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Add Auth Scaffolding
&lt;/h3&gt;

&lt;p&gt;In this step, we can use &lt;a href="https://laravel.com/docs/9.x/starter-kits#laravel-breeze" rel="noopener noreferrer"&gt;Laravel breeze&lt;/a&gt; to scaffold authentication and all other necessary requirements such as password reset and email confirmation logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel/breeze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Add Model and Migration
&lt;/h3&gt;

&lt;p&gt;The next step is to create a migration file that will contain the file name and folder. We can use artisan to create a model and migration file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Files &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;-m&lt;/strong&gt; flag creates a migration file for the &lt;strong&gt;Files Model&lt;/strong&gt;. We can add the following logic to the 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="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Models&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\Database\Eloquent\Factories\HasFactory&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\Database\Eloquent\Model&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;Files&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'path'&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;We can then specify the columns in the files table&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;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&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\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Run the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&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;'files'&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;'path'&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;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Reverse the migrations.
     *
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files'&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;h3&gt;
  
  
  Step 4: Create a generic File Upload Trait
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.php.net/manual/en/language.oop5.traits.php" rel="noopener noreferrer"&gt;Traits&lt;/a&gt; help us &lt;strong&gt;reuse code across multiple classes&lt;/strong&gt;. This trait will contain the logic for &lt;strong&gt;Uploading the file&lt;/strong&gt; , &lt;strong&gt;Renaming the File&lt;/strong&gt; , &lt;strong&gt;Storing the Files in User Specified Folders&lt;/strong&gt; and &lt;strong&gt;Delete Files from storage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, in an e-commerce system, we may want to separate Images into Folders; Main Images, Secondary Images, Banners etc.&lt;/p&gt;

&lt;p&gt;To do so we will use &lt;strong&gt;Illuminate\Http\UploadedFile&lt;/strong&gt; class to work with the files.&lt;/p&gt;

&lt;p&gt;We can also make the trait to be usable with any external disk such as Amazon S3.&lt;/p&gt;

&lt;p&gt;Laravel &lt;strong&gt;supports local file storage and Amazon S3&lt;/strong&gt; out of the box. If you want to &lt;strong&gt;use Google Cloud Storage&lt;/strong&gt; as your storage then you can consider using &lt;a href="https://github.com/Superbalist/laravel-google-cloud-storage" rel="noopener noreferrer"&gt;this package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Either way, whichever storage service you decide to use, the trait should be able to handle it without adding any extra implementations.&lt;/p&gt;

&lt;p&gt;We can create an &lt;strong&gt;App\Traits&lt;/strong&gt; folder in the App directory which will contain all our traits.&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\Traits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Str&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\Http\UploadedFile&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Upload&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;UploadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;UploadedFile&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$disk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'public'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$FileName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$filename&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;storeAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nv"&gt;$folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$FileName&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getClientOriginalExtension&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="nv"&gt;$disk&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;deleteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$disk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'public'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$disk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&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;To compress the images upon upload, we can use one of &lt;a href="https://github.com/spatie/laravel-image-optimizer" rel="noopener noreferrer"&gt;Spatie’s Packages&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require spatie/laravel-image-optimizer 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can have the images compressed automatically when they are uploaded thereby reducing their file size before uploading them to storage. To set it up, we will first need to register it as route middleware in the &lt;strong&gt;app/Http/Kernel.php&lt;/strong&gt; 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="c1"&gt;// app/Http/Kernel.php   &lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$routeMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;   
     &lt;span class="s1"&gt;'optimizeImages'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\Spatie\LaravelImageOptimizer\Middlewares\OptimizeImages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   
   &lt;span class="p"&gt;];&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will then assign the middleware later to the file upload route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Handle File uploads using a Controller
&lt;/h3&gt;

&lt;p&gt;The next step is to Receive Files through a POST request. We will use the &lt;strong&gt;store&lt;/strong&gt; method in the file upload controller to do so.&lt;/p&gt;

&lt;p&gt;We can also check the &lt;a href="https://www.iankumu.com/blog/laravel-validation/" rel="noopener noreferrer"&gt;validations&lt;/a&gt; to ensure that the files uploaded are of the correct type and are the allowed files.&lt;/p&gt;

&lt;p&gt;The file path is also stored in the file table. The file path is returned from our trait after it has renamed the file to be uploaded. The format of the file path will be &lt;strong&gt;Folder/filename and extension&lt;/strong&gt; i.e &lt;strong&gt;Products/HIDvPbozwW.png&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&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\Files&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\Traits\Upload&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\Http\Request&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;FilesController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;))&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;UploadFile&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="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nc"&gt;Files&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;'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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files.index'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'File Uploaded Successfully'&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;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-2-1024x552.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-2-1024x552.png" alt="Laravel File upload"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;File paths in the database&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 6: Add the Route
&lt;/h3&gt;

&lt;p&gt;We can add the route to the &lt;strong&gt;routes/web.php&lt;/strong&gt; file. We can use the middleware we created earlier in our route&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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'upload-files'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;FileController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'store'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'optimizeImages'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Add File Upload UI
&lt;/h3&gt;

&lt;p&gt;We can create a view file and add a file upload form&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-1024x390.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-1024x390.png" alt="Laravel File Upload Form"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;File Upload Form&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8: Add Storage Link(Optional)
&lt;/h3&gt;

&lt;p&gt;Files uploaded using the public disk option are always stored in the &lt;strong&gt;storage/app/public&lt;/strong&gt; folder. We can use the &lt;strong&gt;storage:link&lt;/strong&gt; command to create a symlink to the public folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan storage:link 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 9: View Uploaded Files
&lt;/h3&gt;

&lt;p&gt;Once the files are uploaded to your preferred storage, you can view the file. If you are using the public folder, you can use the &lt;strong&gt;asset helper&lt;/strong&gt; or &lt;strong&gt;public_path&lt;/strong&gt; helper to return the file path. If you are using a third-party storage system such as s3 or Google Cloud storage, you can use the &lt;strong&gt;Storage facade&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Using public folder
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'storage/'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using S3 or GCS
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;disk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'s3'&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;url&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then append the path as your image source and display them on your application.&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="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{asset('storage/'.$file-&amp;gt;path)}}"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"file name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
//or
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{$file-&amp;gt;path}}"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"file name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-1-1024x407.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F09%2Fimage-1-1024x407.png" alt="Laravel File Upload"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Display Files&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;How can I update Files in Laravel?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By default, there is &lt;strong&gt;no intrinsic way&lt;/strong&gt; to update files/images using the default PUT or PATCH request based on&lt;a href="https://stackoverflow.com/questions/64887893/how-to-update-image-with-put-method-in-laravel-rest-api" rel="noopener noreferrer"&gt;this issue&lt;/a&gt;. Therefore, we need to look for another way to do so. We could use a POST request but then &lt;strong&gt;delete a previous file if it exists&lt;/strong&gt; and then upload a new file and update the file path in the database.&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;update_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//POST&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//get the file id and retrieve the file record from the database&lt;/span&gt;
        &lt;span class="nv"&gt;$file_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file_id'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Files&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$file_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;//check if the request has a file&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;//check if the existing file is present and delete it from the storage&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_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&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="nf"&gt;deleteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;//upload the new file&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;UploadFile&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="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'file'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'Products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;//upadate the file path in the database&lt;/span&gt;
        &lt;span class="nv"&gt;$file&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;'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="c1"&gt;//redirect with the success message&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;back&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'File Updated Successfully'&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;We can then define the route to update the 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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'update-file'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;FilesController&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;'update_file'&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;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'optimizeImages'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;How do I upload multiple Files and Images in Laravel?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It is pretty easy. We can &lt;strong&gt;reuse&lt;/strong&gt; our trait and use a &lt;strong&gt;foreach&lt;/strong&gt; loop to upload and store the path in the database.&lt;/p&gt;

&lt;p&gt;We will first update the File Controller to allow for multiple files.&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\Http\Controllers&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\Files&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\Traits\Upload&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\Http\Request&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;FilesController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Upload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nv"&gt;$file_details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

        &lt;span class="c1"&gt;//check if request has files&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'files'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// loop through each file and upload&lt;/span&gt;
 &lt;span class="n"&gt;it&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;$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;'files'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;//Upload to Storage&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;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;UploadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Products'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;//reformat the file details&lt;/span&gt;
                &lt;span class="nb"&gt;array_push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file_details&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="s1"&gt;'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="p"&gt;]);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;//add each file details to database&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;$file_details&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Files&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="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="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;The &lt;strong&gt;store&lt;/strong&gt; method now allows for multiple files to be uploaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How do I resize files in Laravel?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can resize files before storing them using the &lt;a href="https://github.com/Intervention/image" rel="noopener noreferrer"&gt;Intervention Image package&lt;/a&gt;. This package can help you resize images before storing them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Intervention\Image\Facades\Image&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="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;path&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;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Working with files and images can be a daunting task in any application but Laravel makes it easy to work with multiple Storage services using their inbuilt APIs and other third-party packages. &lt;/p&gt;

&lt;p&gt;If you enjoyed this article, you'd love the &lt;a href="https://www.iankumu.com/blog/newsletter/" rel="noopener noreferrer"&gt;Free Laravel Guide&lt;/a&gt; I prepared for you. Be sure to get your guide today.&lt;br&gt;
Thank you for reading&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-file-upload/" rel="noopener noreferrer"&gt;Laravel File Upload: A Complete Tutorial and Guide&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>NGINX vs Apache: Choosing The Best Web Server in 2022</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Sat, 27 Aug 2022 16:06:13 +0000</pubDate>
      <link>https://forem.com/iankumu/nginx-vs-apache-choosing-the-best-web-server-in-2022-42pj</link>
      <guid>https://forem.com/iankumu/nginx-vs-apache-choosing-the-best-web-server-in-2022-42pj</guid>
      <description>&lt;p&gt;&lt;a href="https://www.nginx.com/"&gt;Nginx&lt;/a&gt; and &lt;a href="https://httpd.apache.org/"&gt;Apache&lt;/a&gt; are two of the most popular web servers in the world. They are both powerful and versatile and can be used for a variety of purposes. Nginx is known for its high performance and stability, while Apache is known for its flexibility and ease of use. Both web servers are open source and can be used on a variety of operating systems.&lt;/p&gt;

&lt;p&gt;Most &lt;a href="https://www.iankumu.com/blog/best-laravel-hosting/"&gt;Web hosting providers&lt;/a&gt; provide any of the two and it is up to us to determine which web server better suits our needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Web Server?
&lt;/h2&gt;

&lt;p&gt;A web server is a computer program that runs on a computer and is used to serve content to the World Wide Web. It can also be used to run other programs or provide services.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does a Web Server actually work?
&lt;/h2&gt;

&lt;p&gt;A Web Server &lt;strong&gt;processes requests from the client computers&lt;/strong&gt; and sends back the requested data. It is typically located on an IP address, which is a number that identifies an internet protocol address. The IP address can be used to locate the server on the internet and send its requests.&lt;/p&gt;

&lt;p&gt;A web server uses one of two methods to process requests: &lt;strong&gt;TCP/IP&lt;/strong&gt; or &lt;strong&gt;HTTP&lt;/strong&gt;. When using &lt;strong&gt;HTTP&lt;/strong&gt; , the server responds with HTML pages, images, videos, and other web content that match the request. When using &lt;strong&gt;TCP/IP&lt;/strong&gt; , on the other hand, the server is typically running a single application that receives inbound requests from clients and processes them.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does Nginx Work?
&lt;/h2&gt;

&lt;p&gt;Nginx is a popular web server that has been used in various places for years. It is open-source and can be found on many different operating systems.&lt;/p&gt;

&lt;p&gt;It was created by Igor Sysoev in 2004 and is mostly used as a &lt;strong&gt;reverse proxy&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://www.iankumu.com/blog/nginx-load-balancing/"&gt;load balancer&lt;/a&gt;&lt;/strong&gt;. Nginx also uses TCP and HTTP protocols to handle requests from clients.&lt;/p&gt;

&lt;p&gt;Nginx architecture consists of two parts, &lt;strong&gt;the worker process&lt;/strong&gt; and the &lt;strong&gt;master process&lt;/strong&gt;. The &lt;strong&gt;worker processes&lt;/strong&gt; are responsible for &lt;strong&gt;handling client requests&lt;/strong&gt; while the &lt;strong&gt;master process&lt;/strong&gt; handles &lt;strong&gt;all tasks&lt;/strong&gt; such as startup, configuration changes, logging, health monitoring, etc. It uses &lt;a href="https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale"&gt;event-based architecture&lt;/a&gt; to handle requests. This helps in concurrent connections being handled simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nginx Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Free and Open source&lt;/li&gt;
&lt;li&gt;Nginx is lightweight and has fewer resource requirements than Apache&lt;/li&gt;
&lt;li&gt;It offers a number of features that are not available in Apache&lt;/li&gt;
&lt;li&gt;Is able to handle more traffic than other web servers like Apache&lt;/li&gt;
&lt;li&gt;Nginx provides excellent performance and scalability.&lt;/li&gt;
&lt;li&gt;Easy to configure and deploy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Nginx Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Is not as secure as other web servers like Apache&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Does Apache Work?
&lt;/h2&gt;

&lt;p&gt;Apache is an open-source web server software under the apache software foundation. It was created in the early 1990s by a group of developers at the University of California, Berkeley.&lt;/p&gt;

&lt;p&gt;The Apache server is &lt;strong&gt;structured in different modules&lt;/strong&gt; used for &lt;strong&gt;different purposes&lt;/strong&gt; but all share similar functionality. The Apache configuration includes both installation directories as well as files that are necessary for its operation. It uses a &lt;a href="https://vanseodesign.com/web-design/apache-web-server"&gt;process-based architecture&lt;/a&gt; to handle requests. This results in a single process handling a single request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apache Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Apache is a free and open source HTTP server&lt;/li&gt;
&lt;li&gt;It uses a modular design, which means that you can mix and match modules from different vendors to create your own custom configuration&lt;/li&gt;
&lt;li&gt;Apache offers a lot of security options to protect your website from hackers and other malicious entities&lt;/li&gt;
&lt;li&gt;It has strong performance due to its use of caching algorithms&lt;/li&gt;
&lt;li&gt;There are many add-ons available for the server that allow you to customize its functionality even further&lt;/li&gt;
&lt;li&gt;It is compatible with other web servers such as Nginx and &lt;a href="https://www.lighttpd.net/"&gt;Lighttpd&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Apache Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can be slow&lt;/li&gt;
&lt;li&gt;Consumes a lot of memory (Resource Intensive)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s the Difference Between Apache and NGINX?
&lt;/h2&gt;

&lt;p&gt;NGINX and Apache are the two most popular web servers in the world. They are both open source and have been around for a long time. So what is the difference between them?&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;Well, the biggest difference is that Apache uses a &lt;strong&gt;process-based model&lt;/strong&gt; , while NGINX uses an &lt;strong&gt;event-based model&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To better understand the two architectures, we will use an analogy of &lt;strong&gt;a restaurant&lt;/strong&gt; and a &lt;strong&gt;drive-thru.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At a restaurant, each customer has one waiter serving them. This is how the &lt;strong&gt;process-based model&lt;/strong&gt; works. We have one request(customer) being handled by one process(waiter)&lt;/p&gt;

&lt;p&gt;At a drive-thru, a customer is served by more than one person. One person could be taking the order, another person preparing the order and later another person will pack the order. In this scenario, we have a chain of delegation happening allowing for faster take-out service. This is how the &lt;strong&gt;event-based model&lt;/strong&gt; works under the hood.&lt;/p&gt;

&lt;h4&gt;
  
  
  Apache Architecture
&lt;/h4&gt;

&lt;p&gt;Apache uses a &lt;strong&gt;process-based architecture&lt;/strong&gt; which is a software architecture that was first introduced in the Apache HTTP Server in 2000. It is a set of architectural principles and best practices for building, deploying, and operating high-performance web servers.&lt;/p&gt;

&lt;p&gt;Apache process-based architecture consists of three layers: The &lt;strong&gt;application layer&lt;/strong&gt; is where the user interface is rendered and managed. The &lt;strong&gt;presentation layer&lt;/strong&gt; provides a view of the data to the user. The &lt;strong&gt;data layer&lt;/strong&gt; handles all data processing.&lt;/p&gt;

&lt;p&gt;Processes are created to handle particular requests or tasks, with each process having its own responsibility for handling that request/task. These processes communicate with each other through queues or shared memory to coordinate their work and pass information back up to higher levels of the system as necessary.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nginx Architecture
&lt;/h4&gt;

&lt;p&gt;Nginx &lt;strong&gt;event-based architecture&lt;/strong&gt; is built on the idea that the best way to serve a request is to process it in the order it arrives.&lt;/p&gt;

&lt;p&gt;The Nginx event-based architecture has been designed with scalability in mind and it is also a good fit for microservices. This architecture makes use of global variables and events that are used to trigger actions when certain conditions are met.&lt;/p&gt;

&lt;p&gt;This means that NGINX can handle a lot more traffic than Apache can. It also uses less memory, which is important if you have a lot of traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Balancing Capabilities
&lt;/h3&gt;

&lt;p&gt;Another difference is that &lt;strong&gt;NGINX can act as a &lt;a href="https://www.iankumu.com/blog/nginx-load-balancing/"&gt;load balancer&lt;/a&gt;&lt;/strong&gt;, while Apache cannot. This means that NGINX can &lt;strong&gt;distribute traffic across multiple servers&lt;/strong&gt; , which helps to keep your site up even if one of your servers goes down. Using Nginx as a load balancer can help us take advantage of &lt;a href="https://semaphoreci.com/blog/what-is-canary-deployment"&gt;canary deployments&lt;/a&gt; to our application servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reverse Proxy Capabilities
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nginx can also&lt;/strong&gt;  &lt;strong&gt;act as a reverse proxy&lt;/strong&gt; while Apache cannot. A reverse proxy is able to hide the identity of the application servers.This way all the client applications will only know the identity of the reverse proxy but not the identity of the application servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dVCh7nup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/reverse-proxy-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dVCh7nup--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/reverse-proxy-1024x576.png" alt="nginx reverse proxy" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Reverse Proxy Architecture&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Simplicity
&lt;/h3&gt;

&lt;p&gt;Configuring can be simple depending on your choice of data manipulation. &lt;strong&gt;Apache uses XML&lt;/strong&gt; in its configuration while &lt;strong&gt;Nginx uses JSON&lt;/strong&gt; in its configuration files. Depending on which format you are comfortable with, you can use either.&lt;/p&gt;

&lt;p&gt;I personally prefer Nginx because I am more familiar with JSON and as a result find it easier to configure Nginx as a load balancer, reverse proxy or a general web server. Fine-tuning Nginx performance such as adding &lt;strong&gt;Http 2&lt;/strong&gt; , and &lt;strong&gt;enabling &lt;a href="https://www.imperva.com/learn/performance/gzip/"&gt;Gzip compression&lt;/a&gt;&lt;/strong&gt; is way easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;When it comes to performance, it is dependent on the type of content being served. There are two types of content that are served by a web server; &lt;strong&gt;Static Content&lt;/strong&gt; and &lt;strong&gt;Dynamic Content&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Static Content
&lt;/h4&gt;

&lt;p&gt;Static Content can be described as content that does not change every now and then. These include blog posts, landing pages etc.&lt;/p&gt;

&lt;p&gt;When it comes to &lt;strong&gt;Static Content&lt;/strong&gt; , the &lt;strong&gt;Nginx server seems to be the better option&lt;/strong&gt; as it is able to serve static content in milliseconds compared to Apache. It serves Static Content 2.5 times faster than Apache.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dynamic Content
&lt;/h4&gt;

&lt;p&gt;Dynamic Content on the other hand is the &lt;strong&gt;content that keeps on changing&lt;/strong&gt; based on the reactivity of the application. For example, if you have a video editing application, the content keeps on changing based on the inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apache is able to serve dynamic content better&lt;/strong&gt; than Nginx. Nginx uses external processes such as &lt;a href="https://www.php.net/manual/en/install.fpm.php"&gt;PHP-FPM&lt;/a&gt; to serve dynamic content because it does not support dynamic content natively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Platform
&lt;/h3&gt;

&lt;p&gt;Nginx runs on modern Unix Systems such as &lt;a href="https://www.iankumu.com/blog/best-linux-distros-for-programming/"&gt;Linux&lt;/a&gt; but &lt;strong&gt;does not support Windows&lt;/strong&gt; Based Systems. Apache on the other hand runs on All Unix systems and Windows Based Systems&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use Apache?
&lt;/h2&gt;

&lt;p&gt;You should use Apache if you want &lt;strong&gt;more flexibility and customisation&lt;/strong&gt;. This is because Apache allows you to configure your own modules.&lt;/p&gt;

&lt;p&gt;You should also use Apache if &lt;strong&gt;your application is dealing with a lot of Dynamic Content&lt;/strong&gt;. It is way easier to use the built-in functionalities of Apache to serve dynamic content as opposed to relying on external processes in Nginx to serve the same Dynamic Content.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you use Nginx?
&lt;/h2&gt;

&lt;p&gt;You should use Nginx if you want a lightweight web server. If your &lt;strong&gt;server resources are minimal&lt;/strong&gt; , then Nginx is the best option because it consumes fewer resources as compared to Apache.&lt;/p&gt;

&lt;p&gt;Nginx should be a no brainer if you are dealing with &lt;strong&gt;Static Content&lt;/strong&gt; as it ticks all the boxes when it comes to serving static content.&lt;/p&gt;

&lt;p&gt;If a &lt;strong&gt;&lt;a href="https://www.iankumu.com/blog/nginx-load-balancing/"&gt;load balancer&lt;/a&gt; or a reverse proxy&lt;/strong&gt; is required in your stack,Nginx is your best bet in this scenario.&lt;/p&gt;

&lt;p&gt;Nginx is also a good choice for a web server that &lt;strong&gt;can handle a lot of traffic&lt;/strong&gt; in an efficient way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can Nginx and Apache be Used Together?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;They can both be used together to improve website performance. Nginx can act as a proxy server, which means it can allow Nginx to handle static content while Apache handles dynamic content. This can speed up website loading times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the Apache HTTP server still used?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Apache HTTP Server is still used today. With a &lt;a href="https://www.stackscale.com/blog/top-web-servers/"&gt;31.5% market share&lt;/a&gt;, it is still one of the most used web servers in the world. Nginx, its closest rival, holds a &lt;a href="https://www.stackscale.com/blog/top-web-servers/"&gt;33.5% market share&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What language is Nginx written in?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Nginx Source Code is written in &lt;strong&gt;C programming language&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is Apache so Popular?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Apache is popular because it is open source and is also flexible. The flexibility allows for easy customization and configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is Nginx faster than Apache?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Nginx is faster than Apache because it uses &lt;strong&gt;event-based architecture&lt;/strong&gt; which allows it to process multiple requests using one process.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing
&lt;/h2&gt;

&lt;p&gt;Deciding on a web server for your use case is an important step in setting up your website. Both Web servers serve content to the best of their ability and it is only right to choose a web server that will suit your needs.&lt;/p&gt;

&lt;p&gt;I personally use Nginx as my web server and it is because I find it easier to configure and optimize to suit my needs. I have covered how to deploy a web application using &lt;a href="https://www.iankumu.com/blog/how-to-deploy-a-laravel-app-on-lemp-stack/"&gt;Nginx&lt;/a&gt; and &lt;a href="https://www.iankumu.com/blog/how-to-deploy-laravel-on-apache-server/"&gt;Apache&lt;/a&gt; and having used both I can say I preferred Nginx to Apache.&lt;/p&gt;

&lt;p&gt;What Web Server is your preferred choice? &lt;/p&gt;

&lt;p&gt;If you're interested in getting updated each time I publish a new article, feel free to &lt;a href="https://www.iankumu.com/blog/newsletter/"&gt;sign up for my newsletter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/nginx-vs-apache/"&gt;NGINX vs Apache: Choosing The Best Web Server in 2022&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>nginx</category>
      <category>apache</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Ultimate Guide to Ubuntu Commands for Beginners</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Wed, 24 Aug 2022 08:44:43 +0000</pubDate>
      <link>https://forem.com/iankumu/the-ultimate-guide-to-ubuntu-commands-for-beginners-4gj1</link>
      <guid>https://forem.com/iankumu/the-ultimate-guide-to-ubuntu-commands-for-beginners-4gj1</guid>
      <description>&lt;h2&gt;
  
  
  What is Ubuntu?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ubuntu.com/"&gt;Ubuntu&lt;/a&gt; is a free and open-source operating system. It is based on the Linux kernel and distributed with a GNU userland. Ubuntu has a wide range of support and can be installed on many different devices or used to power your own server. It is one of the &lt;a href="https://www.iankumu.com/blog/best-linux-distros-for-programming/"&gt;best Linux distros used by developers&lt;/a&gt;. It has gained popularity because of how stable it is and how mature its &lt;strong&gt;package manager&lt;/strong&gt; is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Learn These Commands?
&lt;/h2&gt;

&lt;p&gt;Ubuntu commands are very important to learn because they can help you with almost anything you need to do on your computer.&lt;/p&gt;

&lt;p&gt;They can help you &lt;strong&gt;fix any errors&lt;/strong&gt; , &lt;strong&gt;install programs&lt;/strong&gt; , and &lt;strong&gt;manage files&lt;/strong&gt;. Learning these commands not only helps you navigate the command line interface but also helps you understand why some Linux commands are essential in operating a Linux operating system.&lt;/p&gt;

&lt;p&gt;It shows how powerful a terminal can be since you can execute anything on the computer through the terminal. These tasks include &lt;a href="https://www.iankumu.com/blog/linux-permissions/"&gt;changing file permissions&lt;/a&gt;, &lt;strong&gt;renaming files,&lt;/strong&gt;  &lt;strong&gt;check disk space&lt;/strong&gt; just to name a few.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the Basic Ubuntu Commands?
&lt;/h2&gt;

&lt;p&gt;Linux commands are a set of instructions that allow you to interact with the Linux operating system from the command line interface.&lt;/p&gt;

&lt;p&gt;The Ubuntu commands helps you get around your system faster and more efficiently.&lt;/p&gt;

&lt;p&gt;In this section, I am going to split the commands &lt;strong&gt;into their use cases&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands used for System Information
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;lsblk&lt;/strong&gt; – List block devices on the system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mKDw2BH1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mKDw2BH1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-7.png" alt="Ubuntu Commands for Beginners" width="612" height="305"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;lsblk command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lspci&lt;/strong&gt; – List all PCI devices in the system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wM4pon-7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wM4pon-7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-8.png" alt="Ubuntu Commands for Beginners" width="877" height="296"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;lspci command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lshw&lt;/strong&gt; – Show detailed hardware information about the machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WH1EGhmJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WH1EGhmJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-9.png" alt="Ubuntu Commands for Beginners" width="737" height="562"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;lshw command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dmesg&lt;/strong&gt; – Shows kernel messages since last boot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---vXBCCGt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-10-1024x143.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---vXBCCGt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-10-1024x143.png" alt="Ubuntu Commands for Beginners" width="880" height="123"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;dmesg command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;uname&lt;/strong&gt; – Displays the Linux kernel release and architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--svLmxcmn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--svLmxcmn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image-11.png" alt="Ubuntu Commands for Beginners" width="727" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;uname command&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Commands used for File Handling
&lt;/h3&gt;

&lt;p&gt;The following commands are used for file handling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ls&lt;/strong&gt; : – Lists all the files and directories in the current directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wP_-2BGu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wP_-2BGu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/08/image.png" alt="Ubuntu Commands for Beginners" width="802" height="103"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ls command&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;touch&lt;/strong&gt; : – Creates an empty file with a given name or alters a file’s timestamp to match that of a given date and time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;new.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;cp&lt;/strong&gt; :- Copies a file from one place to another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;mv&lt;/strong&gt; :- Moves and renames a file or directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;directory/ /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rm&lt;/strong&gt; :- Removes an existing file or directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;new.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;find&lt;/strong&gt; :- Finds files in a directory and displays the names of those files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find new.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;mkdir&lt;/strong&gt; : – Creates a new directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rmdir&lt;/strong&gt; : – Remove an empty directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rmdir &lt;/span&gt;directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rd&lt;/strong&gt; : – Removes a directory and all of its contents recursively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rd directory/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;make&lt;/strong&gt; :- Creates a new file in a specified location, which must exist and be empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make new.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read more on file permission commands &lt;a href="https://www.iankumu.com/blog/linux-permissions/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ubuntu Commands For Package Installation
&lt;/h3&gt;

&lt;p&gt;This is a list of commands which are the most useful for installing packages in Ubuntu. These commands will work in any Linux distribution, but the package names may be different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get install package name&lt;/strong&gt; – Installs a package from the APT repository&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get update&lt;/strong&gt; – Downloads the package lists from the repositories and “updates” them to get information on the newest versions of packages and their dependencies. Ideally, it updates the “links” of the packages from where the packages will be fetched when we perform an upgrade&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get upgrade&lt;/strong&gt; – fetches new versions of packages existing on the operating system. This command now “upgrades” the packages by”following the links” that were updated using the apt-get update command&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get dist-upgrade&lt;/strong&gt; – installs new packages or removes existing ones on its own during an upgrade&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dpkg -i package-name&lt;/strong&gt; – This command helps in installing Debian-based packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Download/Extract Files Via The Command Line On Ubuntu
&lt;/h3&gt;

&lt;h4&gt;
  
  
  wget
&lt;/h4&gt;

&lt;p&gt;The wget command is an internet utility that can be used to download files from the web. It is a command line tool, which means it will only work in a terminal window. The wget command is very versatile and can be used to download files from different types of servers, as well as individual files from websites.&lt;/p&gt;

&lt;h4&gt;
  
  
  tar
&lt;/h4&gt;

&lt;p&gt;The tar command is a computer program for packaging a set of files into a single file or multiple files. Tar can be used to create, extract, list and verify the contents of archives.&lt;/p&gt;

&lt;h4&gt;
  
  
  unzip
&lt;/h4&gt;

&lt;p&gt;The unzip command is used to extract files from a ZIP archive. It can be used to extract the contents of an archive into the current directory, or into a new directory.&lt;/p&gt;

&lt;h4&gt;
  
  
  zip
&lt;/h4&gt;

&lt;p&gt;Zip is a compression and archive format that was initially developed in the mid-1970s. It was created to replace the “archive” command which had been used on Unix systems.&lt;/p&gt;

&lt;p&gt;The zip file format offers some advantages over tar and other formats: it &lt;strong&gt;can store many files&lt;/strong&gt; , even if they are not part of a hierarchical directory tree, it provides &lt;strong&gt;better compression&lt;/strong&gt; , especially for large files and it is &lt;strong&gt;supported on nearly all computing platforms&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Removing Packages/Uninstalling Software In Ubuntu
&lt;/h3&gt;

&lt;p&gt;The following commands can be used to remove packages from your system:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get remove package_name&lt;/strong&gt; – removes installation files while keeping the configuration data for a package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get autoremove&lt;/strong&gt; – removes packages that were automatically installed because some other package required them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dpkg -P package_name&lt;/strong&gt; – To uninstall a specific configuration file of a program&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get purge package_name&lt;/strong&gt; – removes everything related to a package including the configuration files&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;apt-get autoclean&lt;/strong&gt; – remove files that can no longer be downloaded and are deemed useless&lt;/p&gt;

&lt;h3&gt;
  
  
  Ubuntu/Linux Networking Commands
&lt;/h3&gt;

&lt;p&gt;Below are some of the most common Linux networking commands you should know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ifconfig&lt;/strong&gt; – Configures interface information on a Linux system&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ip addr show&lt;/strong&gt; – Shows an IP address or a list of IP addresses associated with an interface&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ifup&lt;/strong&gt; – Configures network interfaces on a Linux system&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Processes, Closing Programs, And System Resources Commands
&lt;/h3&gt;

&lt;p&gt;Managing processes, closing programs, and system resources are some of the basic tasks that Linux users need to perform on a regular basis. There are various commands that can be used to accomplish these tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;killall&lt;/strong&gt; – kill all running process&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pkill&lt;/strong&gt; – kill process by name&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ps&lt;/strong&gt; – show the running processes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ps -ef&lt;/strong&gt; – show all running processes and their command line arguments&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;kill&lt;/strong&gt; – terminate the specified process ID (PID)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pgrep&lt;/strong&gt; – find all instances of a particular process name, including those without a terminal or any open files. This is useful for finding runaway background processes&lt;/p&gt;

&lt;h3&gt;
  
  
  Ubuntu Authentication/User Account Commands
&lt;/h3&gt;

&lt;p&gt;There are a few commands you can use to manage user accounts and authentication in Ubuntu.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;passwd&lt;/strong&gt; – you can use to change a user’s password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;passwd username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;adduser&lt;/strong&gt; – you can use to create a new user account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;deluser&lt;/strong&gt; – you can use to delete an existing user account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;deluser username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What’s a working directory in Linux?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A working directory is a directory that contains the files that are currently in use by a process.&lt;br&gt;&lt;br&gt;
In Linux, it is the default location for storing temporary files and directories.&lt;br&gt;&lt;br&gt;
The working directory can be accessed using &lt;strong&gt;cd&lt;/strong&gt; command or through the GUI of your Linux distribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How do you find the filename in Linux?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To find out the filename in Linux, you can use the following command:&lt;br&gt;&lt;br&gt;
ls -l&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How do I search for a word in the Ubuntu terminal?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are many ways to search for a word within the Ubuntu terminal, but two of the most common are &lt;strong&gt;grep and locate&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Locate searches for files and directories in your computer’s file system&lt;/strong&gt; , while &lt;strong&gt;grep searches for files in your computer’s data directory.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Are Ubuntu Commands Case-sensitive?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ubuntu commands are case-sensitive&lt;/strong&gt;. The command “ls” is different from the command “Ls” and the command “ls -l” is different from the command “Ls -l”.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing
&lt;/h2&gt;

&lt;p&gt;Ubuntu is one of the most popular Linux operating systems and is used by &lt;a href="https://www.iankumu.com/blog/best-laravel-hosting/"&gt;many hosting providers&lt;/a&gt; and companies in production. It is also used on desktops and as a result, understanding the basic commands can help you immensely.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/ubuntu-commands/"&gt;The Ultimate Guide to Ubuntu Commands for Beginners&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A Complete Beginner’s Guide on Linux Permissions</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Thu, 11 Aug 2022 10:55:39 +0000</pubDate>
      <link>https://forem.com/iankumu/a-complete-beginners-guide-on-linux-permissions-hfk</link>
      <guid>https://forem.com/iankumu/a-complete-beginners-guide-on-linux-permissions-hfk</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2F5xhm2euf0vpeyqsvje13.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5xhm2euf0vpeyqsvje13.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Linux is a Unix-like computer operating system assembled under the model of free and open-source software development and distribution. It is popular among developers and has seen &lt;a href="https://www.iankumu.com/blog/best-linux-distros-for-programming/" rel="noopener noreferrer"&gt;some distros being preferred for programming&lt;/a&gt; across the board.&lt;/p&gt;

&lt;p&gt;One of the key concepts in mastering Linux is understanding &lt;strong&gt;Linux Permissions&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What are Permissions in Linux?
&lt;/h2&gt;

&lt;p&gt;Permissions are a set of rules that determine what a user is allowed to do with the files in Linux. These rules are set for each file and folder separately.&lt;/p&gt;

&lt;p&gt;The three types of permissions are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read&lt;/strong&gt; : allows users to view the contents of the file&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write&lt;/strong&gt; : allows users to modify or delete the contents of the file&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execute&lt;/strong&gt; : allows users to execute it as a program&lt;/p&gt;

&lt;p&gt;The permission model is a mechanism to control access to files/directories in a process known as permission checking. When the permissions of an object need to be changed, they are changed according to the rules in the system.&lt;/p&gt;

&lt;p&gt;Permissions are used when &lt;strong&gt;manipulating file contents&lt;/strong&gt; , such as &lt;strong&gt;moving or deleting them, copying or renaming them, and viewing their content&lt;/strong&gt;. Another use is when granting or denying apps permission to access data on the device, such as contacts, photos, and location.&lt;/p&gt;

&lt;p&gt;The File Manager app requests permission before accessing the user’s entire device.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Should I Care about the Linux Permission Structure?
&lt;/h2&gt;

&lt;p&gt;Permissions in Linux are a crucial part of it, they allow users to control who can access files on their computer.&lt;/p&gt;

&lt;p&gt;They are based on three different types of users: &lt;strong&gt;the owner of the file&lt;/strong&gt; , &lt;strong&gt;the group that owns the file&lt;/strong&gt; , and &lt;strong&gt;other users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To set permissions on a file, one must know which type of user they want to set them for. The owner of a file is able to &lt;strong&gt;read&lt;/strong&gt; , &lt;strong&gt;write&lt;/strong&gt; , and &lt;strong&gt;execute&lt;/strong&gt; the file.&lt;/p&gt;

&lt;p&gt;The group that owns the file is able to read and write the file. Other users have no control over the file other than being able to view it.&lt;/p&gt;

&lt;p&gt;A user can be a member of more than one group. In this case, they must choose which group they want to set their file permissions for.&lt;/p&gt;

&lt;p&gt;The owner of a file and the group that owns the file can change permissions on it later and all other users will have no effect on those changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Commands for Linux File Permissions
&lt;/h2&gt;

&lt;p&gt;This section provides a basic overview of the three commands that affect file permissions.&lt;/p&gt;
&lt;h3&gt;
  
  
  ls -List contents of a directory
&lt;/h3&gt;

&lt;p&gt;The ls command can be used to list the contents of a directory and can take a directory name as an argument, or display what’s in the current working directory when there are no arguments specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists the contents in the current working directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage.png" alt="linux permissions"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ls command&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists &lt;strong&gt;all&lt;/strong&gt; the contents in the current working directory &lt;strong&gt;including hidden files&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage-1.png" alt="linux permissions"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ls -a command&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command shows information about a directory including &lt;strong&gt;file permissions&lt;/strong&gt; , &lt;strong&gt;the number of links&lt;/strong&gt; , &lt;strong&gt;owner name&lt;/strong&gt; , &lt;strong&gt;owner group&lt;/strong&gt; , &lt;strong&gt;file size&lt;/strong&gt; , &lt;strong&gt;time of last modification&lt;/strong&gt; , and the &lt;strong&gt;file or directory name&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fimage-2.png" alt="linux permissions"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ls -l command&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  chmod – Alter file permissions
&lt;/h3&gt;

&lt;p&gt;To modify existing permissions on a file, use the &lt;strong&gt;chmod&lt;/strong&gt; command with a plus or minus symbol before each letter to indicate whether you want to increase or decrease the permissions.&lt;/p&gt;

&lt;p&gt;For example, &lt;strong&gt;chmod u+rwx&lt;/strong&gt; filename changes file permissions so that others can &lt;strong&gt;read, write and execute&lt;/strong&gt; while &lt;strong&gt;users in the group can only read&lt;/strong&gt;. This sets the owner of the file to be the user where u is an arbitrary number and then sets all other permissions to 0 (no permissions). U = user who owns the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +rwx filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command &lt;strong&gt;adds read, write and execute permissions to a file&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; &lt;span class="nt"&gt;-rwx&lt;/span&gt; filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command &lt;strong&gt;removes read, write and execute permissions from a file&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that “r” is for read, “w” is for write, and “x” is for execute. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  chown – Change file ownership
&lt;/h3&gt;

&lt;p&gt;chown is a command-line utility in Unix, Linux and other Os which &lt;strong&gt;changes the owner of a file&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It requires root privileges to assign ownership of any file other than the current user’s home directory.&lt;/p&gt;

&lt;p&gt;The command-line syntax is &lt;strong&gt;chown [-R [-h] ] owner:newowner&lt;/strong&gt;  &lt;strong&gt;filename&lt;/strong&gt; where filename is the name of the file that is to be changed in ownership.&lt;/p&gt;

&lt;p&gt;The -R flag recursively changes all subdirectories and their files.The -h flag changes &lt;strong&gt;only&lt;/strong&gt; the specified file’s owner &lt;strong&gt;without changing the group&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; owner:newowner /path/to/directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command gives someone the &lt;strong&gt;ownership of the directory&lt;/strong&gt; , and &lt;strong&gt;all files&lt;/strong&gt; and &lt;strong&gt;subdirectories&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Commands for Linux File Permissions
&lt;/h2&gt;

&lt;p&gt;In this part, I’ll discuss some of the &lt;strong&gt;less-known&lt;/strong&gt; commands for working with file attributes.&lt;/p&gt;

&lt;h3&gt;
  
  
  chattr – Change Attributes of a File or Directory
&lt;/h3&gt;

&lt;p&gt;By default, files in Linux are &lt;strong&gt;immutable&lt;/strong&gt;. This means that once the file has been created, &lt;strong&gt;it cannot be changed&lt;/strong&gt;. &lt;strong&gt;In order to change the attribute of a file&lt;/strong&gt; or directory, you have to &lt;strong&gt;use the chattr command followed by a string or a set of strings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s take an example of the file / &lt;strong&gt;etc/passwd&lt;/strong&gt;. if we run the command &lt;strong&gt;ls -l&lt;/strong&gt; we can get the following output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 root root 4096 Aug 8 11:36 /etc/passwd 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add attributes to a file we can use the &lt;strong&gt;chattr&lt;/strong&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chattr +i /etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can verify the immutability using the &lt;strong&gt;lsattr&lt;/strong&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsattr
&lt;span class="nt"&gt;----i-----------&lt;/span&gt; ./etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find more information on chattr in &lt;a href="https://www.tecmint.com/chattr-command-examples/" rel="noopener noreferrer"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  find – Search for Files in Linux
&lt;/h3&gt;

&lt;p&gt;Finding files is easier than you think. Below are some quick tips to help you find and locate the files you need in the file system.&lt;/p&gt;

&lt;p&gt;To locate files in the &lt;strong&gt;current folder&lt;/strong&gt; with a specific extension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To list files with a &lt;strong&gt;specific name and their parent directory&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"my_file.txt"&lt;/span&gt; &lt;span class="nt"&gt;-print&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to search for a file that is &lt;strong&gt;in your current working directory&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"my file.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can learn more about find &lt;a href="https://www.geeksforgeeks.org/find-command-in-linux-with-examples/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  lsattr – List Attribute of Files or Directories
&lt;/h3&gt;

&lt;p&gt;lsattr is a command-line utility that &lt;strong&gt;lists the attributes of files/directories&lt;/strong&gt;. The information listed below should be used as an example when using lsattr.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsattr myfile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  touch – Update Timestamp on a File
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://phoenixnap.com/kb/touch-command-in-linux" rel="noopener noreferrer"&gt;touch&lt;/a&gt; is a command line utility for &lt;strong&gt;updating the access and modification times on one or more files or directories&lt;/strong&gt;. This will update the access and modification times on all files in the current directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates the access time of a file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nt"&gt;-am&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will update the access and modification times on all files in the current directory recursively.&lt;/p&gt;

&lt;h3&gt;
  
  
  unlink – Delete a Directory or File
&lt;/h3&gt;

&lt;p&gt;The unlink command is used to &lt;strong&gt;delete a directory or file from a file system&lt;/strong&gt;. The original name of the directory/file will be deleted, along with any hard links that might have been created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;unlink&lt;/span&gt; /path/to/some-directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Change Linux File &amp;amp; Folder Permissions on a Root or Standard User Account?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Permissions are set by using three different classifications: owner, group, and others.&lt;br&gt;&lt;br&gt;
The owner of a file is the person who created it. The group of a file is the people who have access to that file if it’s been shared with them. And others are everyone else who doesn’t fall into those two categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a group in Linux?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;A group is a &lt;strong&gt;set of users who share permissions to files in a given directory&lt;/strong&gt;. A user who belongs to the group can access these files, but cannot change their permissions or ownership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to reset permissions Linux&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;It is important to reset permissions on your Linux server so that it is secure. To do this, you need to log in as root and use the following command: &lt;strong&gt;chmod -R 777 /home/testuser&lt;/strong&gt; The chmod command &lt;strong&gt;sets permissions on the given directory, making all files, subdirectories and directories read-only for the user and group testuser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to reset ownership in Linux&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The root user is the default owner of all files and directories in a Linux system. When a user creates a file within a directory, they automatically become the owner of that file/directory. The root user can change the ownership of any file/directory by using the &lt;strong&gt;chown command&lt;/strong&gt;. If you are logged in as root and you wish to reset ownership for all files and directories, you can use this command:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;chown -R root: root *&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
This command will change the owner for all files and directories to root with a recursive option set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a sticky bit permission in Linux?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;A sticky bit permission is a permission that is set on a directory (or any file system object) that causes all new files created in the directory (or other objects) to inherit the permission.&lt;br&gt;&lt;br&gt;
The sticky bit permission is set by using the &lt;strong&gt;chmod command&lt;/strong&gt; with a plus character (+) followed by an r, which sets the read and write permissions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SUID permission in Linux&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The Linux operating system &lt;strong&gt;assigns a unique identifier to every user&lt;/strong&gt;. This identifier is called the user ID or UID. The Linux system also assigns a group ID (GID) to each account that is associated with it. &lt;strong&gt;SUID stands for Set User ID&lt;/strong&gt; and it is an attribute of files in Unix-like OS that determines &lt;strong&gt;what operations the file’s owner can perform on the file versus what operations other users can perform on the file&lt;/strong&gt;. A SUID program runs with the permissions of its owner rather than with those of its original (non-owner) user and group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Does chmod 775 Mean?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;chmod 775 means that &lt;strong&gt;all users in the group&lt;/strong&gt; can read, write, and execute a file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Does chmod 777 Mean?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;chmod 777 means that read, write and execute access is &lt;strong&gt;granted to all users&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Linux permissions are the first thing to consider when looking at any Linux system. It is important to know what the permissions mean and what to do when they are not correct. Linux permissions can be a little tricky to wrap your head around, but once you know the basics, you’ll be able to use them to your advantage. I hope this guide was able to shed some light on some of the most important Linux permissions. If you enjoyed reading, you can read about the &lt;a href="https://www.iankumu.com/blog/best-linux-distros-for-programming/" rel="noopener noreferrer"&gt;best Linux distros for programming&lt;/a&gt;. Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/linux-permissions/" rel="noopener noreferrer"&gt;A Complete Beginner’s Guide on Linux Permissions&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How To Configure Nginx as a Load Balancer</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Sat, 06 Aug 2022 15:38:09 +0000</pubDate>
      <link>https://forem.com/iankumu/how-to-configure-nginx-as-a-load-balancer-2ag3</link>
      <guid>https://forem.com/iankumu/how-to-configure-nginx-as-a-load-balancer-2ag3</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;What is load balancing?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Load balancing involves effectively distributing incoming network traffic across a group of backend servers. A load balancer is tasked with distributing the load among the multiple backend servers that have been set up. There are multiple types of load balancers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Load balancer &lt;/li&gt;
&lt;li&gt;Network Load Balancer &lt;/li&gt;
&lt;li&gt;Gateway load balancer &lt;/li&gt;
&lt;li&gt;Classic Load balancer &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are multiple load balancer examples and all have different use cases&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.haproxy.org/" rel="noopener noreferrer"&gt;Haproxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nginx.com/" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://ath.sourceforge.net/mod_athena_doc/html/index.html" rel="noopener noreferrer"&gt;mod_athena&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://opentsdb.net/docs/build/html/user_guide/utilities/varnish.html" rel="noopener noreferrer"&gt;Varnish&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://balance.inlab.net/" rel="noopener noreferrer"&gt;Balance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.linuxvirtualserver.org/whatis.html" rel="noopener noreferrer"&gt;Linux Virtual Server(LVS)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I am going to cover &lt;strong&gt;Nginx&lt;/strong&gt; as a load balancer.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is Nginx Load Balancing?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt; is a high-performance web server which can also be used as a load balancer. Nginx load balancing refers to the process of distributing web traffic across multiple servers using Nginx.&lt;/p&gt;

&lt;p&gt;This ensures that no single server is overloaded and that all requests are handled in a timely manner. Nginx uses a variety of algorithms to determine how to best distribute traffic, and it can also be configured to provide failover in case one of the servers goes down.&lt;/p&gt;

&lt;p&gt;You can use either &lt;strong&gt;Nginx open source&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://www.nginx.com/products/nginx/" rel="noopener noreferrer"&gt;Nginx Plus&lt;/a&gt;&lt;/strong&gt; to load balance HTTP traffic to a group of servers.&lt;/p&gt;

&lt;p&gt;Personally, I use Nginx open source to set up my load balancers and that is what I am going to show you in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Advantages of load balancing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Load balancing helps in scaling an application by handling traffic spikes without increasing cloud costs. It also helps remove the problem of a single point of failure. Because the load is distributed, if one server crashes, the service would still be online.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Configuring Nginx as a load balancer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We can follow the steps to configure the Nginx load balancer.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Installing Nginx&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The first step is to install Nginx. Nginx can be installed in Debian, Ubuntu or CentOS. I am going to use Ubuntu which I have configured on my &lt;a href="https://www.iankumu.com/blog/recommends/contabo/" rel="noopener noreferrer"&gt;Contabo VPS.&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure Nginx as a load balancer
&lt;/h3&gt;

&lt;p&gt;The next step is to configure Nginx. We can create a new configuration file for the load balancer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;/etc/nginx/sites-available/&lt;/span&gt;
&lt;span class="s"&gt;sudo&lt;/span&gt; &lt;span class="s"&gt;nano&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;

&lt;span class="s"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="c1"&gt;# This server accepts all traffic to port 80 and passes it to the upstream. &lt;/span&gt;
   &lt;span class="c1"&gt;# Notice that the upstream name and the proxy_pass need to match.&lt;/span&gt;

   &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

      &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;mydomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="s"&gt;proxy_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

          &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


          &lt;span class="kn"&gt;proxy_redirect&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&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;We will need to define the &lt;strong&gt;upstream directive&lt;/strong&gt; and &lt;strong&gt;server&lt;/strong&gt; directive in the file. &lt;strong&gt;Upstream defines where Nginx will pass the requests upon receiving them.&lt;/strong&gt; It contains upstream server group (backend) IP addresses to which requests can be sent to based on the load balancing method chosen. By default, Nginx uses a &lt;strong&gt;round-robin&lt;/strong&gt; load balancing method to distribute the load across the servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The server segment&lt;/strong&gt; defines the port 80 through which Nginx will receive requests. It also contains a &lt;strong&gt;proxy_pass&lt;/strong&gt; variable&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;proxy_pass&lt;/strong&gt; variable is used to tell NGINX &lt;strong&gt;where to send traffic that it receives&lt;/strong&gt;. In this case, the proxy_pass variable is set to point to 3 servers. This tells NGINX to forward traffic that it receives to any of the upstream servers’ IPs provided. Nginx acts as both a &lt;strong&gt;reverse proxy&lt;/strong&gt; and a &lt;strong&gt;load balancer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;reverse proxy&lt;/strong&gt; is a server that &lt;strong&gt;sits in between backend servers and intercepts requests from clients.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Selecting a load-balancing method&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The next step is to determine the &lt;strong&gt;load balancing method&lt;/strong&gt; to use. There are multiple load balancing methods we can use. They include:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Round Robin&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Round Robin&lt;/strong&gt; is a load balancing method where each server in a cluster is given an equal opportunity to process requests. This method is often used in web servers, where each server request is distributed evenly among the servers.&lt;/p&gt;

&lt;p&gt;The load is distributed in rotation meaning that each server will have its time to execute a request. For example, if you have three upstream servers, A, B and C, then the load balancer will first distribute the load to A then to B and finally to C before redistributing the load to A. It is fairly simple and does have its fair share of imitations.&lt;/p&gt;

&lt;p&gt;One of the limitations is that you will have &lt;strong&gt;some servers idle&lt;/strong&gt; simply because they will be waiting for their turn. In this example, if A is given a task and executes it in a second, it would then mean it would be idle until it is next assigned a task. By default, &lt;strong&gt;Nginx uses round robin to distribute load among servers&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Weighted Round Robin&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To solve the issue of &lt;strong&gt;server idleness&lt;/strong&gt; , we can use &lt;strong&gt;server weights&lt;/strong&gt; to instruct Nginx on which servers should be given the most priority. It is &lt;strong&gt;one of the most popular load balancing methods&lt;/strong&gt; used today.&lt;/p&gt;

&lt;p&gt;This method involves assigning a weight to each server and then distributing traffic among the servers based on these weights. This ensures that servers with more capacity receive more traffic, and helps to prevent overloading of any one server.&lt;/p&gt;

&lt;p&gt;This method is often used in conjunction with other methods, such as &lt;strong&gt;session Persistence&lt;/strong&gt; , to provide an even distribution of load across all servers. The application server with the &lt;strong&gt;highest weight parameter will be given priority(more traffic)&lt;/strong&gt; as compared to the server with the least number(weight).&lt;/p&gt;

&lt;p&gt;We can update the Nginx configuration to include the server weights&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt; &lt;span class="s"&gt;weight=5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt; &lt;span class="s"&gt;weight=3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&lt;/span&gt; &lt;span class="s"&gt;weight=1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

      &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&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;h4&gt;
  
  
  &lt;strong&gt;Least Connection&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The least connection load balancing method is a popular technique used to distribute workloads evenly across a number of servers. The method works by routing each new connection request to the server with the &lt;strong&gt;fewest active connections&lt;/strong&gt;. This ensures that all servers are used equally and that no single server is overloaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;least_conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

      &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&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;h4&gt;
  
  
  &lt;strong&gt;Weighted Least Connection&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The Weighted Least Connection load balancing method is a technique used to distribute workloads across multiple computing resources, such as servers, in order to &lt;strong&gt;optimize performance and minimize response times&lt;/strong&gt;. This technique takes into account the number of active connections each server has and assigns weights accordingly. The goal is to distribute the workload in a way that balances the load and minimizes response times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;least_conn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt; &lt;span class="s"&gt;weight=5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt; &lt;span class="s"&gt;weight=4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&lt;/span&gt; &lt;span class="s"&gt;weight=1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

      &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&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;h4&gt;
  
  
  &lt;strong&gt;IP Hash&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The IP Hash load balancing method uses a &lt;strong&gt;hashing algorithm to determine which server should receive each incoming packet.&lt;/strong&gt; This is useful when multiple servers are behind a single IP address and you want to ensure that each packet from a given client IP address is routed to the same server. It takes the &lt;strong&gt;source IP address and destination IP address&lt;/strong&gt; and &lt;strong&gt;creates a unique hash key&lt;/strong&gt;. It is then used to allocate a client to a particular server.&lt;/p&gt;

&lt;p&gt;This is very important in the case of &lt;a href="https://semaphoreci.com/blog/what-is-canary-deployment" rel="noopener noreferrer"&gt;canary deployments&lt;/a&gt;. It allows us as developers to roll out changes to a subsection of users so that they can test and provide feedback before shipping it out as a feature to all the users.&lt;/p&gt;

&lt;p&gt;The advantage of this approach is that it can provide better performance than other methods, such as round-robin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;ip_hash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

      &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&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;h4&gt;
  
  
  &lt;strong&gt;URL Hash&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;URL Hash load balancing also uses a hashing algorithm to determine which server will receive each request based on the URL.&lt;/p&gt;

&lt;p&gt;It is also similar to the Ip Hash load balancing method but the difference here is that we hash specific URLs as opposed to hashing IPs.This ensures that all requests are evenly distributed across the servers, providing improved performance and reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Restart Nginx
&lt;/h3&gt;

&lt;p&gt;Once you have configured the load balancer with the correct load balancing method, you can restart Nginx for the changes to take effect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Proxying HTTP traffic to a group of servers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A proxy server is a server that &lt;strong&gt;acts as an intermediary between a client and another server&lt;/strong&gt;. A proxy server can be used to allow clients to access a group of servers, such as a group of web servers, by forwarding requests from the client to the appropriate server.&lt;/p&gt;

&lt;p&gt;The proxy server can also provide &lt;strong&gt;&lt;a href="https://www.iankumu.com/blog/laravel-cache/" rel="noopener noreferrer"&gt;caching&lt;/a&gt;&lt;/strong&gt;, which can improve performance by reducing the need to send requests to the server for each page view. Nginx acts can act as a &lt;strong&gt;Forward proxy or a reverse proxy&lt;/strong&gt;. The &lt;strong&gt;difference&lt;/strong&gt; between a forward proxy and a reverse proxy is that a &lt;strong&gt;forward&lt;/strong&gt;  &lt;strong&gt;proxy sits in front of multiple clients&lt;/strong&gt; and a &lt;strong&gt;reverse proxy sits in front of multiple backends&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A forward proxy &lt;strong&gt;protects the identity of the clients&lt;/strong&gt; while a reverse &lt;strong&gt;proxy protects the identity of the backend servers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fforward-proxy-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Fforward-proxy-1024x576.png" alt="nginx load balancing:Forward Proxy"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Forward Proxy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Freverse-proxy-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.iankumu.com%2Fblog%2Fwp-content%2Fuploads%2F2022%2F08%2Freverse-proxy-1024x576.png" alt="nginx load balancing: Reverse Proxy"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Reverse Proxy&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Load balancing with HTTPS enabled&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Load balancing with HTTPS enabled is a great way to improve the performance of your website. By using a load balancer, you can distribute the load of your website across multiple servers, which can help to reduce the strain on any one server.&lt;/p&gt;

&lt;p&gt;Additionally, by enabling HTTPS, you can ensure that all communications between the servers and visitors to your site are encrypted, which can help to keep your site safe and secure.&lt;/p&gt;

&lt;p&gt;It does come with its fair share of problems. On problem is that for each request a &lt;strong&gt;&lt;a href="https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/" rel="noopener noreferrer"&gt;TLS Handshake&lt;/a&gt;&lt;/strong&gt; and a &lt;strong&gt;&lt;a href="https://www.techopedia.com/definition/29029/dns-lookup" rel="noopener noreferrer"&gt;DNS lookup&lt;/a&gt;&lt;/strong&gt; have to occur which might lead to delayed responses.&lt;/p&gt;

&lt;p&gt;I personally have my &lt;strong&gt;backend application servers communicate with the load balancer using HTTP&lt;/strong&gt; (&lt;a href="https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/" rel="noopener noreferrer"&gt;SSL Termination&lt;/a&gt;) and the &lt;strong&gt;load balancer communicates with the clients through HTTPS&lt;/strong&gt;. This way, there are no TLS Handshakes and DNS Lookups to be considered when routing requests to application servers.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Health checks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Load balancers are often used to distribute incoming traffic across a group of servers, in order to avoid overloading any single server. Health checks are a vital part of ensuring that the load balancer is able to correctly route traffic, as they can help to identify when a server is down or not functioning properly.&lt;/p&gt;

&lt;p&gt;Nginx can monitor the health of our HTTP servers in an upstream group. Nginx can perform &lt;strong&gt;Passive Health checks&lt;/strong&gt; and &lt;strong&gt;Active health checks&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Passive health checks
&lt;/h3&gt;

&lt;p&gt;NGINX analyzes transactions as they take place and tries to restore failed connections for passive health checks. NGINX identify the server as unavailable and temporarily halt transmitting requests to it until it is deemed active again if the transaction still cannot be resumed.&lt;/p&gt;

&lt;p&gt;For an upstream server to be marked as unavailable, we need to define two parameters in the upstream directive; &lt;strong&gt;failed_timeout&lt;/strong&gt; and &lt;strong&gt;max_fails&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;failed_timeout&lt;/strong&gt; sets the time during which a number of failed attempts must happen for the server to be marked unavailable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;max_fails&lt;/strong&gt; sets the number of failed attempts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.100&lt;/span&gt; &lt;span class="s"&gt;max_fails=3&lt;/span&gt; &lt;span class="s"&gt;fail_timeout=60s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.101&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="mf"&gt;10.2&lt;/span&gt;&lt;span class="s"&gt;.0.102&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;
  
  
  Active Health Checks
&lt;/h3&gt;

&lt;p&gt;NGINX can periodically check the health of upstream servers by sending special health‑check requests to each server and verifying the correct response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;health_check&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 have not used Active health checks as they seem to be applicable for Nginx Plus. You can read more on Active health checks &lt;a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Self-managed load balancer vs. managed service&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are two main types of load balancers: &lt;strong&gt;self-managed&lt;/strong&gt; and &lt;strong&gt;managed&lt;/strong&gt;. Self-managed load balancers are usually less expensive, but require more technical expertise to set up and maintain. Managed load balancers are more expensive but often come with more features and support.&lt;/p&gt;

&lt;p&gt;If you want to sleep well at night 😂 then managed load balancers are way better as they remove the headache of constantly debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Limiting the number of connections&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One way to improve the performance of a load balancer is to limit the number of connections that it tries to establish to each server. This can prevent the load balancer from overloading any one server and can help to ensure that each server has a fair share of the traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are Reverse Proxy and Load Balancer Similar?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes, reverse proxy and load balancer are similar in many ways. Both can be used to improve the performance and availability of a website or application. Both can also be used to distribute traffic among multiple servers.&lt;/p&gt;

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

&lt;p&gt;Load balancing is a good way to distribute requests across application instances. It provides high availability and ensures server health is always high. Using the Nginx load balancer to distribute load is beneficial as it serves as both a reverse proxy and a load balancer. It is also open source and thus you can get more from Nginx. I hope this article was able to help you set up an Nginx load balancer. If you have any questions feel free to ask them in the comment section. Thank you for reading.&lt;/p&gt;

&lt;p&gt;If you're interested in getting updated each time I publish a new article, feel free to &lt;a href="https://www.iankumu.com/blog/newsletter/" rel="noopener noreferrer"&gt;sign up for my newsletter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/nginx-load-balancing/" rel="noopener noreferrer"&gt;How To Configure Nginx as a Load Balancer&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog" rel="noopener noreferrer"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>nginx</category>
      <category>loadbalancing</category>
      <category>webdev</category>
    </item>
    <item>
      <title>12 Best Linux Distros For Programming in 2022</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Sun, 24 Jul 2022 11:12:24 +0000</pubDate>
      <link>https://forem.com/iankumu/12-best-linux-distros-for-programming-in-2022-4l55</link>
      <guid>https://forem.com/iankumu/12-best-linux-distros-for-programming-in-2022-4l55</guid>
      <description>&lt;p&gt;Linux is a Unix-like operating system that was originally created by Linus Torvalds. Linux is typically packaged in a Linux distribution. It is free and open source.&lt;/p&gt;

&lt;p&gt;A Linux distribution (distro) is an operating system made from a software collection, which is based upon the Linux kernel and, often, a package management system. Distributions are used to bundle together all of the necessary software to run an operating system, including the kernel, libraries, utilities and applications.&lt;/p&gt;

&lt;p&gt;There are many different distributions (“distros”) available, each with its own benefits and drawbacks. Some are better suited for certain tasks than others. In this article, we will take a look at 12 of the best Linux distros for developers.&lt;/p&gt;

&lt;p&gt;Gnome is a popular desktop environment for Linux that is known for being user-friendly and easy to use. It is a good choice for beginners or those who are not familiar with the Linux kernel.&lt;/p&gt;

&lt;p&gt;Distros that are based on Debian or Ubuntu (such as Mint, Elementary, and Zorin) are also good choices for developers as they are easy to set up and use. These distros come with a large number of pre-installed applications and drivers, making them ideal for those who want to get started with programming right away.&lt;/p&gt;

&lt;p&gt;For more experienced developers and Linux enthusiasts, there are also a number of “minimal” distros that do not come with any pre-installed applications. These distros require the user to install and set up everything from scratch, which can be a good learning experience. However, it is important to note that these distros are not suitable for beginners.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What makes a good Linux distro for programming?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are a few key things to look for in a good Linux distro for development and programming. Firstly, it should come with a &lt;strong&gt;good selection of pre-installed programming tools, development tools and languages&lt;/strong&gt;. Secondly, it should have a relatively &lt;strong&gt;short release cycle&lt;/strong&gt; , so that you can always be up-to-date with the latest versions of tools and languages. Lastly, it should be &lt;strong&gt;easy to install new software packages and updates&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to choose the best Linux distro for you if you are a programmer?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Choosing the best Linux distro for your needs can be tricky. There are hundreds of Linux distributions available, and each has its own release cycle, programming language support, and desktop environment.&lt;/p&gt;

&lt;p&gt;Fedora is a good choice for developers who want to stay on the bleeding edge of technology. Its release cycle is shorter than most other distros, so you’ll always have the latest and greatest software available. Ubuntu is a good choice for those who want a more stable release cycle. It’s also a good choice if you want to use a specific programming language, as there are many Ubuntu derivatives that cater to specific languages.&lt;/p&gt;

&lt;p&gt;Ultimately, the best Linux distro for you is the one that meets your specific needs. If you’re not sure what those needs are, try out a few different distros and see which one feels right for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Is Choosing a Distro Important?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are hundreds of distros available, so why is it important to choose the right one? For developers, choosing the right distro is important because it can make a big difference in terms of stability, security, and performance. A distro that is well-suited for development will come with the right tools pre-installed and will be easy to install new software on. Bleeding edge distros are great for developers who want to always have the latest and greatest software, but they can be more unstable. If you’re looking for a more stable development environment, you may want to choose a distro that lags behind the latest releases by a few months. Another factor to consider when choosing a popular distro is the package manager. Some package managers are better at handling dependencies than others. If you’re not sure which package manager to use, ask around or look for reviews online.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Is Linux Better for Developers and Programmers?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Linux is a great choice for programmers and developers for a number of reasons. First, it is an open-source operating system, which means that anyone can contribute to its development. Second, there are many different programming languages available for Linux, so you can choose the one that best suits your needs. Third, Linux distributions are available for a variety of different desktop environments, so you can find one that fits your workflow. Finally, Ubuntu is a popular Linux distribution that is easy to use and has a lot of support from the community.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Which Is The Best Linux Distributions For Programming 2022?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This is a list of the best Linux distributions for programming for various users.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;strong&gt;Ubuntu (best for beginners)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ubuntu.com/"&gt;Ubuntu&lt;/a&gt; is a great choice for &lt;strong&gt;beginner programmers&lt;/strong&gt; and Linux newbies. It is a distro based on Debian and is easy to install and has a lot of online resources to help you get started. Plus, it is free! For programmers, the Ubuntu Long Term Support (LTS) release provides a stable development environment that they don’t need to upgrade every six months. If you are a beginner Linux user or new to the Linux ecosystem, then this is the best option for you. With Ubuntu, you will be up to speed in getting started with Linux commands and package managers. Many programming languages are supported and as a result, it is easy to adopt and a good choice for programming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9_hmU1lh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/ubuntu.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9_hmU1lh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/ubuntu.webp" alt="Ubuntu" width="720" height="372"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Ubuntu)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;strong&gt;Manjaro Linux (best for intermediate programmers&lt;/strong&gt;)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://manjaro.org/"&gt;Manjaro&lt;/a&gt; is a great choice for &lt;strong&gt;intermediate programmers&lt;/strong&gt;. It is based on Arch Linux and has a lot of the same features, but is much easier to install and use. It is one of the best distros for intermediate developers or programmers. Combining all the power of Arch Linux, it suits beginners looking for an Arch alternate. Moreover, Manjaro comes in three editions GNOME, KDE, and XFCE. It also has its own repositories, so you don’t have to worry about using Arch User Repository(AUR).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ixnIm5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Distrowatch-1024x640.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ixnIm5Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Distrowatch-1024x640.png" alt="Manjaro Linux" width="880" height="550"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Distrowatch)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;strong&gt;Arch Linux (best for advanced programmers)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://archlinux.org/"&gt;Arch Linux&lt;/a&gt; is a great choice for &lt;strong&gt;advanced programmers&lt;/strong&gt;. It is a very lightweight distribution that can be easily customized to your needs. The Arch User Repository (AUR) is a great resource for finding and installing software. The Arch community is very friendly and helpful, and there is a lot of documentation available. If you identify yourself as an advanced programmer or you want some challenge then go for arch Linux&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7dujHvKp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/arch-1024x576.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7dujHvKp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/arch-1024x576.webp" alt="Arch Linux" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Linux Config)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;strong&gt;Kali Linux&lt;/strong&gt; (best for security researchers)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.kali.org/"&gt;Kali Linux&lt;/a&gt; is a Debian-derived Linux distribution designed for &lt;strong&gt;digital forensics and penetration testing&lt;/strong&gt;. It is maintained and funded by Offensive Security Ltd. The development team comprises more than 600 people, with a large community of contributors.&lt;/p&gt;

&lt;p&gt;It’s the most popular choice for security programmers due to its vast collection of security-related tools. These tools can be used to test the security of systems and find vulnerabilities. Ethical hackers and security researchers frequently use Kali Linux to perform hack exploits on other systems. If you are looking for a Linux distro that will help you in penetration and security programming, then look no further. Developers, as well as security researchers, can gain a lot of benefits by using Kali Linux as their choice of Linux operating system&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WEAsdgIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/kali-1024x574.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WEAsdgIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/kali-1024x574.jpg" alt="Kali Linux" width="880" height="493"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Kali Linux)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;strong&gt;Fedora&lt;/strong&gt; (best for server programmers)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://getfedora.org/en/workstation/"&gt;Fedora Workstation&lt;/a&gt; is a popular choice for &lt;strong&gt;server programmers&lt;/strong&gt; due to its &lt;strong&gt;stability and wide range of software packages&lt;/strong&gt;. It is also easy to customize and extend, making it a versatile platform for developing and deploying server applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K62wbtII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/fedora.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K62wbtII--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/fedora.webp" alt="Fedora" width="650" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: How to Geek)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;strong&gt;openSUSE&lt;/strong&gt; (best for system admins)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.opensuse.org/"&gt;OpenSUSE&lt;/a&gt; is a great choice for &lt;strong&gt;system administrators and developers who want a stable and reliable operating system&lt;/strong&gt;. It is one of the oldest Linux systems that was &lt;a href="https://www.maketecheasier.com/history-of-linux-distros/"&gt;created in 1992&lt;/a&gt;. It is well-supported and comes with a wide range of tools and features that make it easy to administer a server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OHPmZh9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/opensuse-1024x576.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OHPmZh9B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/opensuse-1024x576.png" alt="Opensuse Linux" width="880" height="495"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Wikipedia)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;strong&gt;Raspberry Pi&lt;/strong&gt; OS(best for education purposes)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.raspberrypi.com/software/"&gt;Raspberry Pi OS&lt;/a&gt;(previously called Raspbian) is a Linux distro that is &lt;strong&gt;optimized for the Raspberry Pi hardware&lt;/strong&gt;. Like Ubuntu or Linux Mint, it is also based on Debian. It is the official operating system for the Raspberry Pi and comes with a wide range of software that is suitable for &lt;strong&gt;education&lt;/strong&gt; , &lt;strong&gt;programming&lt;/strong&gt; , and &lt;strong&gt;general use&lt;/strong&gt;. It provides a programming environment for Raspberry Pi software development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ho2GxS08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/raspberry-pi-1024x439.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ho2GxS08--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/raspberry-pi-1024x439.webp" alt="Rapsberry Pi Os Linux" width="880" height="377"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image credit: Tom’s Hardware)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;strong&gt;Drauger OS&lt;/strong&gt; (best for game programmers)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://draugeros.org/"&gt;Drauger OS&lt;/a&gt; is a great option for &lt;strong&gt;game programmers&lt;/strong&gt;. It is based on Ubuntu, so it has all of the features and benefits that come with that operating system. It provides a good development platform for game programmers who are interested in Linux gaming. In addition, Drauger OS comes with a number of features specifically designed for game development, such as a custom kernel and support for Vulkan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C3cBD5bH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/drauger-1024x570.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C3cBD5bH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/drauger-1024x570.png" alt="Drauger Os Linux" width="880" height="490"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Medium)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;strong&gt;Zorin OS&lt;/strong&gt; (best for windows based programmers)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://zorin.com/os/"&gt;Zorin OS&lt;/a&gt; is a great option for programmers &lt;strong&gt;coming from Windows or macOS&lt;/strong&gt;. It’s based on Ubuntu, so it’s easy to use and familiar for anyone who’s used Windows before. Plus, it comes with all the tools you need to get started programming right away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kjCBVfJt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Zorin-OS.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kjCBVfJt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Zorin-OS.jpg" alt="Zorin Os" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit:Tecmint)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;strong&gt;Gentoo/Sabayon Linux (best for customizations)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.gentoo.org/"&gt;Gentoo&lt;/a&gt;and &lt;a href="https://www.sabayon.org/"&gt;Sabayon&lt;/a&gt; Linux are two of the most popular distros &lt;strong&gt;for customizations&lt;/strong&gt;. They both offer a wide range of options and tools to customize your system. Gentoo is known for its flexibility and customizability, while Sabayon is known for its ease of use and user-friendly interface. Sabayon Linux is the best Linux distro for developers and system designers who want to customise the feel of their Linux operating system&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o9CVhPdw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/sabayon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o9CVhPdw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/sabayon.png" alt="Sabayon" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Sabayon(Image Credit: Wikimedia)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. &lt;strong&gt;Linux Mint (best for general purpose use)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://linuxmint.com/"&gt;Linux Mint&lt;/a&gt; is a great choice for general purpose use. It is based on Ubuntu, so it has all of the same features and benefits. It has some extra features that make it even more user-friendly. For example, it comes with pre-installed software that makes it easy to get started with using Linux.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ficdxIA5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/linux-mint.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ficdxIA5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/linux-mint.png" alt="Linux Mint" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Wikimedia)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. &lt;strong&gt;Android-x86 (best for Android programmers)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.android-x86.org/"&gt;Android-x86&lt;/a&gt; is an open-source project that aims to bring the Android operating system to x86-based PCs and laptops. It is a great choice for Android programmers who want to develop and test their apps on a desktop or laptop. The project provides a live and bootable ISO image that can be used to run Android on your PC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v4zmwtHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Android-x86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v4zmwtHA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/Android-x86.png" alt="" width="121" height="121"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;(Image Credit: Wikipedia)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Ubuntu Best For Programming?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes, Ubuntu is best for programming because it is an open-source operating system that is popular among developers and supports most programming languages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can I become a Linux Pro?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;There is no one-size-fits-all answer to this question, as the best way to become a Linux Pro may vary depending on your level of experience and expertise. However, some tips on how to become a Linux Pro include: &lt;strong&gt;studying&lt;/strong&gt; and &lt;strong&gt;practising regularly&lt;/strong&gt; , &lt;strong&gt;attending conferences and workshops, and networking with other Linux professionals&lt;/strong&gt;. Additionally, it is important to &lt;strong&gt;stay up-to-date with the latest trends&lt;/strong&gt; and developments in the Linux community to polish your Linux expertise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are there alternative Linux desktop options to consider?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Yes, there are alternative Linux desktop options to consider. For example, you could try the LXDE or Xfce desktop environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is Debian so Popular?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Debian is a very popular Linux distribution for several reasons. It is &lt;strong&gt;stable&lt;/strong&gt; , &lt;strong&gt;well-supported&lt;/strong&gt; , and has &lt;strong&gt;a large community of users and developers&lt;/strong&gt;. Debian is also &lt;strong&gt;easy to install&lt;/strong&gt; and use, and it comes with a wide range of software applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which Linux distro does Linus Torvalds use?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Linus Torvalds uses &lt;strong&gt;Fedora&lt;/strong&gt; as his main workstation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Fedora better than Debian?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;There is no simple answer to this question as it depends on what you are looking for in an operating system. Fedora is a popular choice for those who want a &lt;strong&gt;stable and reliable system&lt;/strong&gt; , while Debian is often preferred by those who want &lt;strong&gt;a more customizable experience&lt;/strong&gt;. Ultimately, the best operating system for you is the one that meets your needs and preferences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you prefer stability or bleeding-edge software?&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I prefer stability. I like my software to work well and not have any glitches. I don’t mind if it’s not the newest version, as long as it’s stable.&lt;/p&gt;

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

&lt;p&gt;There are many different Linux distributions available, and choosing the best one for programming can be a difficult task. However, I believe that the best Linux distro for programming is &lt;strong&gt;Ubuntu&lt;/strong&gt;. Ubuntu is a popular distribution that is easy to use and comes with a wide range of features. It also has a large community of users and developers who can help you if you run into any problems. It is also widely used in servers and as a result, learning it can be a case of killing two birds with one stone. What Linux distro do you think is the best for programming?&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/best-linux-distros-for-programming/"&gt;12 Best Linux Distros For Programming in 2022&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Laravel Cache: How To Speed Up Your Load Time</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Fri, 15 Jul 2022 09:05:58 +0000</pubDate>
      <link>https://forem.com/iankumu/laravel-cache-how-to-speed-up-your-load-time-fnn</link>
      <guid>https://forem.com/iankumu/laravel-cache-how-to-speed-up-your-load-time-fnn</guid>
      <description>&lt;p&gt;&lt;a href="https://aws.amazon.com/caching/"&gt;Caching&lt;/a&gt; plays a vital role in optimizing the performance of a web application. According to &lt;a href="https://www.nytimes.com/2012/03/01/technology/impatient-web-users-flee-slow-loading-sites.html?pagewanted=all"&gt;this article&lt;/a&gt;, google engineers discovered that 400ms is long enough to cause users to leave a site. That’s how crucial load time affects bounce rates currently. Slow load speeds could affect conversion rates in e-commerce sites as Amazon stands to lose &lt;a href="https://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales"&gt;1.6 billion in sales&lt;/a&gt; for every one second in load time.&lt;/p&gt;

&lt;p&gt;Caching is an essential part of the software development process if you care about the scalability and performance of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is Laravel Caching?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Laravel provides a robust and easy-to-use implementation of caching and supports multiple caching backends. Through this support, you can switch between caching backends to suit your needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hY6Qw6Bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/laravel-cache-architecture-1024x683.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hY6Qw6Bc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/laravel-cache-architecture-1024x683.png" alt="laravel cache architecture" width="880" height="587"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Cache Architecture&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.techopedia.com/definition/6306/cache-hit"&gt;cache hit&lt;/a&gt; occurs when data is available in cache memory and as a result, the application does not query the database. A &lt;a href="https://hazelcast.com/glossary/cache-miss/"&gt;cache miss&lt;/a&gt;, on the other hand, occurs when data is not present in the cache memory and as a result, the application has to query the database.&lt;/p&gt;

&lt;p&gt;Laravel helps use model the same architecture using its inbuilt cache system.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Benefits of Caching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the benefits of caching is that it &lt;strong&gt;can reduce the workload on your application servers&lt;/strong&gt;. For example, you can cache database queries, API responses and file contents thereby reducing server overheads.&lt;/p&gt;

&lt;p&gt;Another benefit is that you can &lt;strong&gt;cache third-party API responses&lt;/strong&gt; thereby reducing the chances of hitting a throttle limit or monthly request limit. For example, if your application is interacting with a third-party API say &lt;a href="https://openweathermap.org/api"&gt;OpenWeatherMap API&lt;/a&gt;, instead of making a call to the OpenWeatherMap API each time, we can store the response in a cache and update it every 1 hour thereby reducing the number of requests made.&lt;/p&gt;

&lt;p&gt;These are some of the benefits of caching.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Tradeoffs of Caching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Although caching has a lot of benefits, there are some drawbacks we need to be aware of. The first drawback is &lt;strong&gt;having outdated data in the cache.&lt;/strong&gt; Let’s imagine we have some record stored in a cache with a time to live of 1 hour. In the event, that there is an update in the records, the cache may not be updated leading to outdated data being used as opposed to fresh data.&lt;/p&gt;

&lt;p&gt;Another drawback is that it &lt;strong&gt;can be difficult to debug errors&lt;/strong&gt;. It can be quite hard to detect points of failure in an application because records are stored in the cache. Let’s imagine we have a complex query to the database that does a lot of computations. Because we have a cache in place, we would not know about the complex query computation simply because the results might be cached and at surface level, the application might seem to be okay but deep down there are memory leaks that were shipped to production.&lt;/p&gt;

&lt;p&gt;All in all, as much as there are drawbacks, the benefits outweigh the drawbacks and one would benefit massively from implementing caching in their application.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Configuration and Setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Laravel comes already pre-configured to handle caching. It supports popular caching services such as &lt;a href="https://memcached.org/"&gt;Memcached&lt;/a&gt;, &lt;a href="https://redis.io/"&gt;Redis&lt;/a&gt;, &lt;a href="https://aws.amazon.com/dynamodb"&gt;DynamoDB&lt;/a&gt;and the default relational database. Data can also be stored in a file.&lt;/p&gt;

&lt;p&gt;Since Laravel supports multiple cache services, it uses &lt;a href="https://laravel.com/docs/9.x/cache#driver-prerequisites"&gt;drivers&lt;/a&gt;to determine which cache service is in use. Some of the drivers are &lt;strong&gt;database&lt;/strong&gt; , &lt;strong&gt;redis&lt;/strong&gt; , &lt;strong&gt;memcached&lt;/strong&gt; , &lt;strong&gt;database&lt;/strong&gt; , &lt;strong&gt;dynamodb&lt;/strong&gt; , &lt;strong&gt;file&lt;/strong&gt; and &lt;strong&gt;array.&lt;/strong&gt; Depending on your stack needs, you can use any of the drivers to suit your needs. For me, I use &lt;strong&gt;file driver in development&lt;/strong&gt; and &lt;strong&gt;redis driver in production&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Using Laravel Cache Commands&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Laravel provides a Cache &lt;a href="https://laravel.com/docs/9.x/facades"&gt;Facade&lt;/a&gt; that enables us to interact with our cache system. We can use the methods available in the Facade to add and remove data from the cache easily.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Cache Methods&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cache::remember()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This method helps us &lt;strong&gt;retrieve data from the cache&lt;/strong&gt; if it is present in the cache or &lt;strong&gt;store it if it is not present&lt;/strong&gt;. It requires 3 parameters; &lt;strong&gt;the cache key&lt;/strong&gt; , &lt;strong&gt;ttl(time to live)&lt;/strong&gt; and a &lt;strong&gt;callback function&lt;/strong&gt;. &lt;strong&gt;Cache Key&lt;/strong&gt; is a unique string that will be used to retrieve data from the cache. &lt;strong&gt;TTL is the amount of time in seconds&lt;/strong&gt; the data will be stored in the cache. The Callback function is a function that will be invoked in the case the cache is empty.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addHour&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'subcategories'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we have a cache key of products, &lt;strong&gt;TTL&lt;/strong&gt; of 1 hour(3600 seconds) and a callback function that queries the database in the case of a &lt;a href="https://hazelcast.com/glossary/cache-miss/"&gt;cache miss&lt;/a&gt;. A cache miss occurs when data is not present in the cache memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cache::get()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This method &lt;strong&gt;retrieves items from the cache&lt;/strong&gt; memory. In the event of a Cache miss, it returns null as the value.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nv"&gt;$categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$categories&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Cache::forget()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This method helps &lt;strong&gt;remove items from the cache&lt;/strong&gt;. This is extremely useful when we want to update the cache records with new data.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Cache::has()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This method determines &lt;strong&gt;if an item exists&lt;/strong&gt; in the cache. It returns true if it exists and false otherwise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&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="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
  &lt;span class="c1"&gt;//execute some code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Cache::put()&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This method is used to &lt;strong&gt;store data in the cache&lt;/strong&gt; memory.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'key'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are some of the useful Cache methods you will use in your day-to-day development. There are other methods present which you can find them &lt;a href="https://laravel.com/docs/9.x/cache#cache-usage"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using Laravel Cache Commands in Production&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we know the basic commands, we can use them in our production codebase. When an application is &lt;a href="https://www.iankumu.com/blog/how-to-deploy-laravel-on-apache-server/"&gt;deployed to production&lt;/a&gt;, there are numerous things we need to factor in. The first one is &lt;strong&gt;speed&lt;/strong&gt;. It is known that &lt;a href="https://www.sqlshack.com/poor-sql-query-design-sql-query-performance-killer-basics/"&gt;bad SQL query designs&lt;/a&gt; can cause memory leaks and lead to slow applications. One way we can avoid such issues is to introduce a cache system.&lt;/p&gt;

&lt;p&gt;The Cache would sit in between our Laravel application and the database and would return data in the case of a &lt;a href="https://www.techopedia.com/definition/6306/cache-hit"&gt;cache hit&lt;/a&gt; or retrieve the data from the database and store it in memory in the case of a cache miss.&lt;/p&gt;

&lt;p&gt;In Laravel, we can use the &lt;strong&gt;remember&lt;/strong&gt; method to handle this for us. It will return cached data if it is present and store it in memory by retrieving the data from the database. This way, we are able to improve the speed of the application by reducing the number of queries made to the database.&lt;/p&gt;

&lt;p&gt;The second thing we need to factor in is &lt;strong&gt;efficiency&lt;/strong&gt;. If we are writing a REST API in Laravel, we would want to &lt;strong&gt;paginate our responses&lt;/strong&gt; as we don’t want to return thousands of records in one response.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;But how do we deal with paginated data in Cache?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It is actually pretty easy. We can paginate the results being fetched from the database. However, to store them in the cache, we would need to &lt;strong&gt;know which page’s results are stored so that when we retrieve the data we can return the results for the correct page&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To do so, we can &lt;strong&gt;append the cache key with the page number&lt;/strong&gt; and thus have the results for the different pages stored differently in memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&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;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$currentPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'page'&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="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$currentPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addHour&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Categories&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'subcategories'&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;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&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;h2&gt;
  
  
  &lt;strong&gt;Update the Cache&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;One of the&lt;/strong&gt;  &lt;strong&gt;challenges in caching is updating the cache&lt;/strong&gt;. It is challenging because it is hard to know &lt;strong&gt;when to update&lt;/strong&gt; the cache, especially in production. Since we won’t be managing the cache manually, we would need a way to update the cache automatically.&lt;/p&gt;

&lt;p&gt;Luckily, Laravel provides a way in which we can update the cache.&lt;/p&gt;

&lt;p&gt;Now that we have data in the cache, we would want to update as soon as new data is available. This is where we would use the &lt;strong&gt;forget&lt;/strong&gt; method. This would remove the data for a specific cache key from the memory. In development, this would not be an issue since we can just clear the cache once new data is available. This is not the case in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;So how do we update the cache at scale?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is where &lt;a href="https://laravel.com/docs/9.x/eloquent#observers"&gt;Model Observers&lt;/a&gt; come in handy. &lt;strong&gt;Observers listen to events&lt;/strong&gt; on a given model and execute code based on the triggered events. For example, if a new record is added to the database, we would want the cache to be updated to have the new data.&lt;/p&gt;

&lt;p&gt;We can drop the previous data that was in the cache memory and update it at the next get request.&lt;/p&gt;

&lt;p&gt;To create an observer, we can use the &lt;strong&gt;make:observer&lt;/strong&gt; Artisan command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We then need to &lt;strong&gt;register the Observer&lt;/strong&gt; in the &lt;strong&gt;AppServiceProvider boot method&lt;/strong&gt; in the &lt;strong&gt;App\Providers\AppServiceProvider.php&lt;/strong&gt; 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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Category&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Observers\CategoriesObserver&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;boot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CategoriesObserver&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now add the &lt;strong&gt;Cache::forget()&lt;/strong&gt; logic in the observer.&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\Observers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Category&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&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;CategoriesObserver&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle the Category "created" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Handle the Category "updated" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Handle the Category "deleted" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&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;This will remove the data based on certain events on a Model.&lt;/p&gt;

&lt;p&gt;While this is a simple solution for a small application, it is definitely not a good one for a production-ready application. This is because, in production, you probably have paginated results. This is because the data stored in the cache contains the page number as part of the cache key.&lt;/p&gt;

&lt;h3&gt;
  
  
  So how do we update the cache with paginated results?
&lt;/h3&gt;

&lt;p&gt;In this case, we would need to write a &lt;strong&gt;for loop&lt;/strong&gt; that would &lt;strong&gt;remove all the data for all the cache keys&lt;/strong&gt; for a model. I would first write a generic function in a &lt;a href="https://www.php.net/manual/en/language.oop5.traits.php"&gt;trait&lt;/a&gt; through which I can use it anywhere in my codebase. Traits help us reuse our code in multiple classes. I will create a Traits folder in the app directory and create a ClearCache trait in the &lt;strong&gt;App\Traits&lt;/strong&gt; folder&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\Traits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;ClearCache&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * This function is responsible for clearing the cache when a specific cache key is passed.
     * It is useful for paginated Resources that are cached
     * @param int $key The cache key index
     */&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;clearCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&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;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$newKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$i&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="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$newKey&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;forget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$newKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&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;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With this, you are able to clear the cache and prepare the cache to be ready to store new data once it is available.&lt;/p&gt;

&lt;p&gt;Now that we have the trait ready, we can &lt;strong&gt;update our Category Observer to use the trait&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Category&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\Traits\ClearCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&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;CategoriesObserver&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;ClearCache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Handle the Category "created" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;created&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&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="nf"&gt;clearCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Handle the Category "updated" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&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="nf"&gt;clearCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Handle the Category "deleted" event.
     *
     * @param \App\Models\Category $category
     * @return void
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Category&lt;/span&gt; &lt;span class="nv"&gt;$category&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="nf"&gt;clearCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'categories'&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;&lt;strong&gt;Observers listen&lt;/strong&gt; to events that happen to &lt;strong&gt;one record only&lt;/strong&gt;. For example, the updated method only executes if one record is updated. While this is good by design, there may exist some cases where you are executing updates on multiple records at the same time. In this case, the updated event would not fire and thus the cache would not be updated.&lt;/p&gt;

&lt;h3&gt;
  
  
  So how do we update the cache when multiple records are updated in the database?
&lt;/h3&gt;

&lt;p&gt;In this case, we would need to just clear the cache manually. We can add the &lt;strong&gt;clearcache method&lt;/strong&gt; from the trait in a controller after records have been updated. Though &lt;strong&gt;I would advise against it&lt;/strong&gt; , this could be a workaround for that particular scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Clear the Cache&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To clear the cache, we can use the &lt;strong&gt;cache:cache&lt;/strong&gt; Artisan command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After implementing caching in my application, this was the major improvement I saw in my API requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uG73oCDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/before-1-1024x331.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uG73oCDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/before-1-1024x331.gif" alt="laravel cache" width="880" height="284"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Before Caching&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ycA5dVE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/after-1024x331.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ycA5dVE8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/07/after-1024x331.gif" alt="laravel cache" width="880" height="284"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;After Caching&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Caching helps &lt;strong&gt;improve the performance of an application&lt;/strong&gt;. It does come with its fair share of challenges but the challenges are worth the effort as this can skyrocket your application to greater heights. I hope this article was able to shed some light on how to implement Laravel cache and some of the best practices. If you want to improve your application’s performance, you can read this article on &lt;a href="https://www.iankumu.com/blog/laravel-scheduler/"&gt;Laravel Scheduling&lt;/a&gt;. Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-cache/"&gt;Laravel Cache: How To Speed Up Your Load Time&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>redis</category>
      <category>caching</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Laravel Hide Id from URLs: A Simple Implementation</title>
      <dc:creator>Ian Kumu</dc:creator>
      <pubDate>Sat, 18 Jun 2022 21:24:01 +0000</pubDate>
      <link>https://forem.com/iankumu/laravel-hide-id-from-urls-a-simple-implementation-2f73</link>
      <guid>https://forem.com/iankumu/laravel-hide-id-from-urls-a-simple-implementation-2f73</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ever wondered how big services such as youtube tend to hide their ids in their URLs? I am sure you have seen how youtube masks the ids by showing a random string in the query string of a video URL. We also can mask and hide our database ids in Laravel thereby reducing any security risks that would arise in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why hash ids?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are multiple ways to hide/mask the ids in the URLs. The first way is by using UUIDs. UUIDs are &lt;strong&gt;Universally Unique Identifiers&lt;/strong&gt; that can be used instead of the default incremental ids. Laravel comes with support for UUIDs. You can check &lt;a href="https://www.larashout.com/using-uuids-in-laravel-models"&gt;this article&lt;/a&gt; on how to implement UUIDs in Laravel.&lt;/p&gt;

&lt;p&gt;The second way is hashing the ids using a unique salt. This means that the salt can be set at the server level and have the ids hashed and returned to the frontend as unique strings.&lt;/p&gt;

&lt;p&gt;In this article, I am going to hash ids using salt and return them as random encoded strings. To do so, I will use &lt;a href="https://github.com/vinkla/laravel-hashids"&gt;this package&lt;/a&gt; to accomplish that.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Installation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To start using it we can download the package using composer into our application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require vinkla/hashids
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Configuration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The next step is to publish the configurations. We can use the &lt;strong&gt;vendor:publish&lt;/strong&gt; command to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Vinkla&lt;/span&gt;&lt;span class="se"&gt;\H&lt;/span&gt;&lt;span class="s2"&gt;ashids&lt;/span&gt;&lt;span class="se"&gt;\H&lt;/span&gt;&lt;span class="s2"&gt;ashidsServiceProvider"&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will publish the &lt;strong&gt;config/hashids.php&lt;/strong&gt; file which contains the package configurations. The file looks like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oCOEPt5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oCOEPt5R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-1.png" alt="hashids configuration file" width="880" height="1205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a few things we need to change. As you can see the default connection has been set to main and as a result, we need to update the main connection for the package. The first thing we need to do is to &lt;strong&gt;uncomment the alphabet&lt;/strong&gt; part. This is the set of strings the package will use to create a random hash for the database ids.&lt;/p&gt;

&lt;p&gt;The next step is to &lt;strong&gt;define a salt&lt;/strong&gt;. This is &lt;strong&gt;any additional data that will be used as input in hashing of the ids&lt;/strong&gt;. By default it is empty so you can leave it as is or add anything. I am going to use my name as the salt.&lt;/p&gt;

&lt;p&gt;The last thing is the &lt;strong&gt;length&lt;/strong&gt; of the hash. This will determine the number of characters the random string will contain. I personally prefer using a hash of 4 characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s1"&gt;'connections'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

        &lt;span class="s1"&gt;'main'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'salt'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Ian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'length'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'alphabet'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;

        &lt;span class="s1"&gt;'alternative'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'salt'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'your-salt-string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'length'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'your-length-integer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// 'alphabet' =&amp;gt; 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'&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 that, this is how the new file should look&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BAR-3_Mn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BAR-3_Mn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-2.png" alt="hashids configuration file" width="880" height="1205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Encoding Model Attributes.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that the package is all set, we can now start &lt;strong&gt;hashing&lt;/strong&gt; the ids. I am going to create a new Blog model and its migration file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Blog &lt;span class="nt"&gt;-mrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;-mrc&lt;/strong&gt; flag will instruct Laravel to generate a Blog Model, Its migration file and a Blog Controller that is resourceful(has all the relevant methods).&lt;/p&gt;

&lt;p&gt;I will just add a simple database schema containing the &lt;strong&gt;id, title and body&lt;/strong&gt; of the blog posts.&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;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&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;'blogs'&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;'title'&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;longText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'body'&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IwIt1XRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IwIt1XRS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-3.png" alt="" width="880" height="1117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to specify the mass assignable variables using the &lt;strong&gt;$fillable&lt;/strong&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pq3iDSDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pq3iDSDl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-4.png" alt="Blog Model" width="880" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now need to mask the id attribute to contain the Hashed id. We can use the &lt;a href="https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor"&gt;&lt;strong&gt;Eloquent Accessor&lt;/strong&gt;&lt;/a&gt; to return a blog article’s id as a hashed string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Vinkla\Hashids\Facades\Hashids&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\Database\Eloquent\Casts\Attribute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Hash the blog ids
     *
     * @return \Illuminate\Database\Eloquent\Casts\Attribute
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;Attribute&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Attribute&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Hashids&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QUIjGgwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QUIjGgwz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-5.png" alt="Hash the id using eloquent accessor" width="880" height="994"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;encode&lt;/strong&gt; method in the &lt;strong&gt;Hashids Facade&lt;/strong&gt; creates a hash using the &lt;strong&gt;salt, alphabets and length&lt;/strong&gt; we had specified in the &lt;strong&gt;config/hashids.php&lt;/strong&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Append Hashed ids to Routes
&lt;/h2&gt;

&lt;p&gt;Once the accessor is set, it is now time to register a route for the blogs. We can use the &lt;strong&gt;resource&lt;/strong&gt; method to register all the routes for the blog Resource in the &lt;strong&gt;routes/web.php&lt;/strong&gt; 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;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blog'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BlogController&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--elFtw-Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--elFtw-Pt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-6.png" alt="hide the id from Urls" width="880" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will return the URLs as &lt;strong&gt;&lt;a href="http://localhost:8000/blog/QVyG"&gt;http://localhost:8000/blog/QVyG&lt;/a&gt;&lt;/strong&gt; as opposed to &lt;strong&gt;&lt;a href="http://localhost:8000/blog/1"&gt;http://localhost:8000/blog/1&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the hashed ids in the controller
&lt;/h2&gt;

&lt;p&gt;The next step is to use the hashed ids in the controller. We can use the &lt;strong&gt;decode&lt;/strong&gt; function in the &lt;strong&gt;Hashids Facade&lt;/strong&gt; to decode the hashed ids. To demonstrate this, I am going to use the default resourceful Controller methods and map them to their corresponding routes. The &lt;strong&gt;decode&lt;/strong&gt; method returns an array of items so we will need to access the first index as seen in the consecutive methods below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Index(/blog)
&lt;/h3&gt;

&lt;p&gt;This method will retrieve all the records from the database and display them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6ovvYIey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6ovvYIey--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-7.png" alt="Retrieve all the blog posts" width="880" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create(/blog/create)
&lt;/h3&gt;

&lt;p&gt;This method returns the view where we can add a blog post&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dmG25E29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dmG25E29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-8.png" alt="Create a blog post" width="880" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now create blog posts normally through the &lt;strong&gt;store&lt;/strong&gt; method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Show(/blog/hashed_id)
&lt;/h3&gt;

&lt;p&gt;This method decodes the hashed id and then returns the article from the database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Vinkla\Hashids\Facades\Hashids&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;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$decoded_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Hashids&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//decode the hashed id&lt;/span&gt;
        &lt;span class="nv"&gt;$blog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Blog&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="nv"&gt;$decoded_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'show'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blog'&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kevcJe57--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kevcJe57--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-9.png" alt="show a blog post and hide the id from the url" width="880" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The article is accessible through &lt;strong&gt;&lt;a href="http://127.0.0.1:8000/blog/Gbqw"&gt;http://127.0.0.1:8000/blog/Gbqw&lt;/a&gt;&lt;/strong&gt; as opposed to &lt;strong&gt;&lt;a href="http://127.0.0.1:8000/blog/1"&gt;http://127.0.0.1:8000/blog/1&lt;/a&gt;&lt;/strong&gt;. We have masked the default blog id to a random string that can only be decoded at the server level thereby increasing the security of our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Edit(/blog/hashed_id/edit)
&lt;/h3&gt;

&lt;p&gt;This method returns the edit view.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Vinkla\Hashids\Facades\Hashids&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;edit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$decoded_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Hashids&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//decode the hashed id&lt;/span&gt;
        &lt;span class="nv"&gt;$blog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Blog&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="nv"&gt;$decoded_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'edit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;compact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blog'&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;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NAmtlSre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NAmtlSre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iankumu.com/blog/wp-content/uploads/2022/06/word-image-1780-10.png" alt="edit a blog post and hide the id from the url" width="880" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Through the view, we can update an article through the update method. We would need to &lt;strong&gt;decode&lt;/strong&gt; the hashed string before updating the article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete(/blog/hashed_id)
&lt;/h3&gt;

&lt;p&gt;We can use the same logic and decode the hashed string, getting the article and then deleting it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Vinkla\Hashids\Facades\Hashids&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;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$decoded_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Hashids&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//decode the hashed id&lt;/span&gt;
        &lt;span class="nv"&gt;$blog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Blog&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="nv"&gt;$decoded_id&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$blog&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'blog.index'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Blog Post Deleted Successfully'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this article, you have learnt how to hide ids from URLs in Laravel using the &lt;a href="https://github.com/vinkla/laravel-hashids"&gt;Hashids&lt;/a&gt; package. There are multiple ways we can use the package to our advantage. Another example is &lt;strong&gt;hashing user ids in a system&lt;/strong&gt;. This will return the user ids as hashed and an example of a URL could be &lt;strong&gt;&lt;a href="http://localhost:8000/users/Gbqw"&gt;http://localhost:8000/users/Gbqw&lt;/a&gt;&lt;/strong&gt; which could be mapped to &lt;strong&gt;&lt;a href="http://localhost:8000/users/1"&gt;http://localhost:8000/users/1&lt;/a&gt;&lt;/strong&gt;. I hope this article was able to shed some light on how to use the package. If you have any questions, feel free to ask them in the comment section. Thank you for reading.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.iankumu.com/blog/laravel-hide-id-from-urls/"&gt;Laravel Hide Id from URLs: A Simple Implementation&lt;/a&gt; appeared first on &lt;a href="https://www.iankumu.com/blog"&gt;Ian Kumu's Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
