<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adnan Babakan (he/him)</title>
    <description>The latest articles on DEV Community by Adnan Babakan (he/him) (@adnanbabakan).</description>
    <link>https://dev.to/adnanbabakan</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%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg</url>
      <title>DEV Community: Adnan Babakan (he/him)</title>
      <link>https://dev.to/adnanbabakan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adnanbabakan"/>
    <language>en</language>
    <item>
      <title>Deploying Minio using Docker Compose</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Mon, 29 Dec 2025 12:57:27 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/deploying-minio-using-docker-compose-m7l</link>
      <guid>https://dev.to/adnanbabakan/deploying-minio-using-docker-compose-m7l</guid>
      <description>&lt;p&gt;Hey there DEV.to community!&lt;/p&gt;

&lt;p&gt;As you might have heard about Minio, it is a free S3 storage server that you can set up and use locally or along your project to leverage the full potential of a powerful storage software and store your files inside with blazing fast response time.&lt;/p&gt;

&lt;p&gt;Here is how to set it up using a Docker Compose file.&lt;/p&gt;

&lt;p&gt;First of all, if you don't have it yet, create a file named &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Defining network
&lt;/h1&gt;

&lt;p&gt;First of all we have to define a network so we can connect our server to it and share it between other services if we tend to do such a thing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;minio-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A bridge network allows your containers communicate with each other if they are on the same network while being isolated from other networks. And only publicly accessible if ports are published.&lt;/p&gt;
&lt;h1&gt;
  
  
  Defining volume
&lt;/h1&gt;

&lt;p&gt;By defining a volume, we can keep our data persistent. Here is how to define one:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minio-volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Defining service
&lt;/h1&gt;

&lt;p&gt;Now it comes to Minio itself. By defining a service using the appropriate image from the docker registry we may start our service:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minio/minio&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_ROOT_USER=root&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_ROOT_PASSWORD=rootpass123&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_DEFAULT_BUCKETS=bucket&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;minio-network&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;minio-volume:/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9222:9000"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9223:9001"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;server"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--console-address"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:9001"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I've named my service &lt;code&gt;minio&lt;/code&gt; which will create a container named after it. You may define another name for your service or define another container name using &lt;code&gt;container_name&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;minio/minio&lt;/code&gt; image is the official image to deploy minio so there won't be a change here.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;environment&lt;/code&gt; variables we define the root username and password. Make sure your password is at elast 8 characters long as it is required by minio.&lt;/p&gt;

&lt;p&gt;Attach the service to your created network using the &lt;code&gt;networks&lt;/code&gt; attribute of the service.&lt;/p&gt;

&lt;p&gt;Minio stores data at &lt;code&gt;/data&lt;/code&gt; so map it to the volume we created before using &lt;code&gt;volumes&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;Minio exposes two ports being &lt;code&gt;9000&lt;/code&gt; for api and &lt;code&gt;9001&lt;/code&gt; for web ui so expose them to public network using &lt;code&gt;ports&lt;/code&gt; attribute.&lt;/p&gt;

&lt;p&gt;And finally start the service using the command added above and DONE!&lt;/p&gt;
&lt;h1&gt;
  
  
  Final docker compose
&lt;/h1&gt;

&lt;p&gt;Here is the final docker compose:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minio-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minio-volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;


&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;minio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minio/minio&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_ROOT_USER=root&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_ROOT_PASSWORD=rootpass123&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MINIO_DEFAULT_BUCKETS=bucket&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;minio-network&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;minio-volume:/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9222:9000"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9223:9001"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;server"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--console-address"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:9001"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I hope this comes in handy and useful to you.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__hidden-navigation-link"&gt;NodeJS Essentials | Free E-Book&lt;/a&gt;


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

          &lt;a href="/adnanbabakan" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adnanbabakan" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Adnan Babakan (he/him)
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Adnan Babakan (he/him)
                
              
              &lt;div id="story-author-preview-content-453379" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adnanbabakan" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Adnan Babakan (he/him)&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 11 '20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" id="article-link-453379"&gt;
          NodeJS Essentials | Free E-Book
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/books"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;books&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;64&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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


&lt;/div&gt;





&lt;p&gt;Feel free to contact me if you have any questions, projects or suggestions to improve this article.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>s3</category>
    </item>
    <item>
      <title>PHP Syntax Cheatsheet [Part 1]</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sun, 28 Dec 2025 12:54:11 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/php-syntax-cheatsheet-part-1-2mc9</link>
      <guid>https://dev.to/adnanbabakan/php-syntax-cheatsheet-part-1-2mc9</guid>
      <description>&lt;p&gt;Hey there DEV.to community!&lt;/p&gt;

&lt;p&gt;Here I am compiling a list of PHP syntax cheatsheet for you all. As for why I am writing this post, PHP was my first programming language, and I still feel like I am in love with it, and it deserves more attention. Thus, trying to spread PHP knowledge for those learning it for the first time or trying to get back to it.&lt;/p&gt;

&lt;p&gt;In this part I will go through basic PHP syntax and in the next part I will discuss the OOP aspect much more in detail.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of Content
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Syntax&lt;/li&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;li&gt;
Variables

&lt;ul&gt;
&lt;li&gt;Variable variables&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Constant

&lt;ul&gt;
&lt;li&gt;Run-time constant&lt;/li&gt;
&lt;li&gt;Compile-time constant&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Types

&lt;ul&gt;
&lt;li&gt;String&lt;/li&gt;
&lt;li&gt;Integer&lt;/li&gt;
&lt;li&gt;Float&lt;/li&gt;
&lt;li&gt;Boolean&lt;/li&gt;
&lt;li&gt;
Array

&lt;ul&gt;
&lt;li&gt;Index-based array&lt;/li&gt;
&lt;li&gt;Key-based array&lt;/li&gt;
&lt;li&gt;Array language construct&lt;/li&gt;
&lt;li&gt;Multi-dimensional arrays&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Null&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Echo and Print&lt;/li&gt;

&lt;li&gt;Casting&lt;/li&gt;

&lt;li&gt;

Operators

&lt;ul&gt;
&lt;li&gt;
Arithmetic operators

&lt;ul&gt;
&lt;li&gt;Summation&lt;/li&gt;
&lt;li&gt;Subtraction&lt;/li&gt;
&lt;li&gt;Multiplication&lt;/li&gt;
&lt;li&gt;Division&lt;/li&gt;
&lt;li&gt;Exponentiation&lt;/li&gt;
&lt;li&gt;Modulo&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Comparison operators

&lt;ul&gt;
&lt;li&gt;Equal and not equal&lt;/li&gt;
&lt;li&gt;Identical and not identical&lt;/li&gt;
&lt;li&gt;Less than and less than or equal&lt;/li&gt;
&lt;li&gt;Greater than and greater than or equal&lt;/li&gt;
&lt;li&gt;Spaceship&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Conditions

&lt;ul&gt;
&lt;li&gt;If&lt;/li&gt;
&lt;li&gt;If, else and elseif&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Switch case&lt;/li&gt;

&lt;li&gt;

Loops

&lt;ul&gt;
&lt;li&gt;For loop&lt;/li&gt;
&lt;li&gt;While loop&lt;/li&gt;
&lt;li&gt;Do while loop&lt;/li&gt;
&lt;li&gt;Foreach loop&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Functions&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Syntax &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;PHP files are named with &lt;code&gt;.php&lt;/code&gt; extension and start with &lt;code&gt;&amp;lt;?php&lt;/code&gt; or &lt;code&gt;&amp;lt;?&lt;/code&gt; and end with &lt;code&gt;?&amp;gt;&lt;/code&gt;. It is good to not that ending tag is not mandatory if you whole file consists of PHP and no HTML afterwards.&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="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or simply:&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="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Comments &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;As for every programming language you need comments to describe your code. PHP provides multiple ways to comment.&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="c1"&gt;// THIS IS A COMMENT&lt;/span&gt;
&lt;span class="c1"&gt;# THIS IS A COMMENT AS WELL&lt;/span&gt;
&lt;span class="cm"&gt;/*
AND THIS IS
A MULTI-LINE COMMENT
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using &lt;code&gt;//&lt;/code&gt; and &lt;code&gt;#&lt;/code&gt;, you may create a single-line comment. And by putting you comment between &lt;code&gt;/*&lt;/code&gt; and &lt;code&gt;*/&lt;/code&gt; you can create a multi-line comment.&lt;/p&gt;
&lt;h1&gt;
  
  
  Variables &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Variables in PHP are defined using &lt;code&gt;$&lt;/code&gt; followed by their name. A variable in PHP isn't typed and can hold any value that PHP offers. A variables value can be changed later on.&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="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;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It is good to know that PHP statements require a semicolon at the end, and it is not optional.&lt;/p&gt;
&lt;h2&gt;
  
  
  Variable variables &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;While it is against the convention, since variables are defined using &lt;code&gt;$&lt;/code&gt;, it is possible to define a variable's name using another variable.&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="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$$v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'HELLO WORLD'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$test&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// HELLO WORLD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I am not encouraging using such an approach, but it is possible, so mentioning it here is an honourable mention.&lt;/p&gt;
&lt;h1&gt;
  
  
  Constant &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A constant is almost like a variable but its value can only be declared once and later on it cannot be changed. By convention constant names are defined in UPPER_SNAKE_CASE.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run-time constant &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A runtime constant can be defined using the &lt;code&gt;define()&lt;/code&gt; 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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MY_CONST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'HELLO'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="no"&gt;MY_CONST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// HELLO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Compile-time constant &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A compile-time constant can be defined using the &lt;code&gt;const&lt;/code&gt; keyword.&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="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;MY_CONST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'HELLO'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="no"&gt;MY_CONST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// HELLO&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Types &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;PHP is a dynamically-typed language, which means you don't need to declare every type you use, yet it is essential to know what you are passing around as values so you can control how it affects your program.&lt;/p&gt;
&lt;h2&gt;
  
  
  String &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A string is a series of characters, such as a name or a full sentence. A PHP string can be defined between quotes &lt;code&gt;'&lt;/code&gt; and double-quotes &lt;code&gt;"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$last_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Babakan'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The difference between a single quote and a double quote is simple. Inside a single-quote, wrap everything is considered literal and will remain as is. But inside a double-quote, variables are evaluated, and their values are placed in the 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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$test1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Hi I am $name'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Hi I am $name&lt;/span&gt;
&lt;span class="nv"&gt;$test2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hi I am &lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Hi I am Adnan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For best practices, it is good to use single quotes and not double quotes, as it can result in unwanted behaviour.&lt;/p&gt;
&lt;h2&gt;
  
  
  Integer &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Integers or simple int is a whole number without a decimal point.&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="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Float &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Floating point numbers (one of the most controversial features in programming languages) is a number with a decimal point.&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="nv"&gt;$pi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;7.98&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Boolean &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A boolean or a bool is simply a value of &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. They are used in conditions and many places to switch between two different actions. Later on we will discuss comparison operators, which will result in a boolean.&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="nv"&gt;$k1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$k2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Remember that &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;'true'&lt;/code&gt; and respectively &lt;code&gt;false&lt;/code&gt; and &lt;code&gt;'false'&lt;/code&gt; are two different things. If you put them inside a quotation or double quotation they are considered a string and not a boolean. Just like a simple text.&lt;/p&gt;
&lt;h2&gt;
  
  
  Array &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;An array is a series of values that can be accessed using their index or pre-defined keys. So we will separate arrays in PHP into two different categories: Index-based and key-value arrays.&lt;/p&gt;
&lt;h3&gt;
  
  
  Index-based array &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;An index-based array is simply wrapped with &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;]&lt;/code&gt; and each element is separated with a comma. Values (elements) of an array in PHP can be of any type and they don't have to be the same.&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="nv"&gt;$a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Hello'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In order to access an element here is how we do 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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Hello'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a1&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="c1"&gt;// 'Hello'&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a1&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="c1"&gt;// 2&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a1&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="c1"&gt;// true&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// 3.14&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Remember that indices start from 0 in PHP and not 1. (There is a logical reason behind it but it is beyond the scope of this post. Yet you can research for yourself why it starts from 0.)&lt;/p&gt;
&lt;h3&gt;
  
  
  Key-based array &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A key based array is defined differently. Each key-value pair is define using &lt;code&gt;key =&amp;gt; value&lt;/code&gt; syntax and separated by a comma again.&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="nv"&gt;$a2&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'age'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And in order to access the value we do the same, but this time instead of an index we provide the defined key:&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="nv"&gt;$a2&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'age'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a2&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="c1"&gt;// Adnan&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$a2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'age'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// 25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It is good to know that most keys are strings but the values can be of any type again.&lt;/p&gt;
&lt;h3&gt;
  
  
  Array language construct &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It is possible to define both index-based and key-based arrays using a function-like construct named &lt;code&gt;array()&lt;/code&gt;. What we had learnt before is just a short form for this constrcut.&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="nv"&gt;$a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'age'&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Multi-dimensional arrays &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Arrays can hold arrays and that is what we call a multi-dimensional array.&lt;br&gt;
Here is a simple one:&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="nv"&gt;$m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$m&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$m&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;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// 6&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It is good to note that a key-based array can be multi-dimensional as well:&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="nv"&gt;$o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'friends'&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;'Arian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ata'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Mahdi'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Erfan'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$o&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'friends'&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="c1"&gt;// Ata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Null &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Null is a special value that means nothing.&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="nv"&gt;$n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And that's it. While being simple you will see so many uses of this special value.&lt;/p&gt;
&lt;h1&gt;
  
  
  Echo and Print &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;echo()&lt;/code&gt; and &lt;code&gt;print()&lt;/code&gt; are most used functions to print something to the standard output. Being a web client or simply terminal.&lt;br&gt;
You can use &lt;code&gt;echo&lt;/code&gt; and &lt;code&gt;print&lt;/code&gt; without parentheses.&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="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Hello World'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s1"&gt;'How are you doing?'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Casting &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Casting means converting one data type to another. For instance converting a number to a string or vice-versa. Not all data types can be converted to each other. The simple rule is that it has to make sense. (I know this is vague but consider it suffecient for now :) ).&lt;/p&gt;

&lt;p&gt;To cast a value to another type simply put the targeted type inside parentheses and before the source 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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;gettype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;gettype()&lt;/code&gt; is a function that returns the data type of the variable.&lt;/p&gt;

&lt;p&gt;The list of castings are as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;(string)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(int)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(float)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(bool)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(array)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(object)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are not seeing &lt;code&gt;object&lt;/code&gt; in the types section above, you are completely right. Objects are more elaborate and will be discussed later in this post.&lt;/p&gt;
&lt;h1&gt;
  
  
  Operators &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Operators are used for multiple purposes, such as arithmetic (mathematical) or comparison reasons. Here are full list of PHP operators.&lt;/p&gt;
&lt;h2&gt;
  
  
  Arithmetic operators &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Arithmetic operatos are used for summation, division and etc. Here is the full list:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;+&lt;/code&gt; Summation &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-&lt;/code&gt; Subtraction &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;*&lt;/code&gt; Multiplication &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;/&lt;/code&gt; Division &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;**&lt;/code&gt; Exponentiation &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;%&lt;/code&gt; Modulo &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This operator is used for getting the remainder of a number divided by another.&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Comparison operators &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Comparison operators are used to compare two values and result in a boolean. They are used in conditions to evaluate a result.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;==&lt;/code&gt; equal and &lt;code&gt;!=&lt;/code&gt;/&lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; not equal &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Check if two values are equal/ not equal independant of their types.&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can use &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt; operator instead of the &lt;code&gt;!=&lt;/code&gt; operator as well.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;===&lt;/code&gt; identical and &lt;code&gt;!==&lt;/code&gt; not identical &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;&amp;lt;&lt;/code&gt; less than and &lt;code&gt;&amp;lt;=&lt;/code&gt; less than or equal &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;&amp;gt;&lt;/code&gt; greater than and &lt;code&gt;&amp;gt;=&lt;/code&gt; greater than or equal &lt;a&gt;&lt;/a&gt;
&lt;/h3&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="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; Spaceship operator &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If the value on the left-hand side is less than the one on the right-hand side the result is equal to &lt;code&gt;-1&lt;/code&gt;. If they are equal the result is equal to &lt;code&gt;0&lt;/code&gt; and if the left-hand side is greater than on the right-hand side the result is equal to &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Conditions &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A condition is a flow-control statement that determines if a block should be run or not, and if not any other blocks will proceed in case it is defined to do so.&lt;/p&gt;
&lt;h2&gt;
  
  
  If &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;if&lt;/code&gt; statement is simply defined as 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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In place of the work &lt;code&gt;condition&lt;/code&gt; there should be a boolean or a comparison that results in a boolean. If the boolean evaluates to &lt;code&gt;true&lt;/code&gt; then the code inside two curly-braces (&lt;code&gt;{&lt;/code&gt; and &lt;code&gt;}&lt;/code&gt;) run.&lt;/p&gt;
&lt;h2&gt;
  
  
  If-else and elseif &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;An else statement is defined immediately after an if statement and the code inside its block is run in case the condition for &lt;code&gt;if&lt;/code&gt; evaluates to &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE GOES HERE&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="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You may also define multiple elseif statements between &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;else&lt;/code&gt; to check other conditions:&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE GOES HERE&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="c1"&gt;// CODE GOES HERE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Switch case &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A switch case checks the value provided to it to be equal to any of its cases, and if not, the &lt;code&gt;default&lt;/code&gt; case is triggered. It is kind of like a chained if-elseif-else statement, but only checking for equality.&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="nv"&gt;$fruit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'apple'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fruit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'banana'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'yellow'&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="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'apple'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'red'&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="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'cucumber'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'green'&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="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'NOT FOUND'&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code above will echo the word &lt;code&gt;red&lt;/code&gt; as &lt;code&gt;$fruit&lt;/code&gt; is equal to apple. After each case, there needs to be a &lt;code&gt;break&lt;/code&gt; statement to break the switch block. The last case/default case doesn't require a &lt;code&gt;break&lt;/code&gt;, but I always include it just for the sake of consistency.&lt;/p&gt;
&lt;h1&gt;
  
  
  Loops &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;As one of my professors once said, a loop statement is the most important statement in programming, as it runs a block of code multiple times. If computers were only to do a thing once, then there would be no need for them.&lt;/p&gt;
&lt;h2&gt;
  
  
  For loop &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A for loop consists of three parts usually, an initilization, a condition and a mutator.&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="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;0&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;10&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="c1"&gt;// CODE HERE RUNS FOR 10 TIMES, FROM 0 to 9.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  While loop &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A while loop only consists of a condition and checks if the condition is true and runs the code block if so.&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="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE HERE RUNS FOREVER&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You may recreate a for loop using a while loop as 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="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&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;while&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;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE HERE RUNS FOR 10 TIMES, FROM 0 to 9.&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Do while loop &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A do while loop runs almost like a while loop with one difference. It runs at least once since it checks the condition afterwards and not at the beginnign.&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="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// CODE HERE RUNS ONCE AND THEN CHECKS THE CONDITION WHICH IS FALSE&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Foreach loop &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A for each loop iterates through a array.&lt;/p&gt;

&lt;p&gt;Here is the sample for an index based array:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$el&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;Inside the loop you may access the &lt;code&gt;$el&lt;/code&gt; variable which is equal to each memeber of the array in each iteration.&lt;/p&gt;

&lt;p&gt;And here is an example for a key-value array:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"b"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"c"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In each iteration, you may access &lt;code&gt;$key&lt;/code&gt; and &lt;code&gt;$value&lt;/code&gt; variables, which correspond to each key and value in the array.&lt;/p&gt;

&lt;p&gt;It is good to know that in both foreach loops demonstrated above, the names &lt;code&gt;$el&lt;/code&gt;, &lt;code&gt;$key&lt;/code&gt; and &lt;code&gt;$value&lt;/code&gt; are arbitrary and can be any valid variable name you desire.&lt;/p&gt;
&lt;h1&gt;
  
  
  Functions &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A function is a block of code that can be reused, have arguments and return a value as well.&lt;/p&gt;

&lt;p&gt;A function in PHP is defined as 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="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$b&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;$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nf"&gt;sum&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="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the next chapter we will discuss OOP aspect of PHP and then in the later chapter the more advanced tricks of PHP are going to be included.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__hidden-navigation-link"&gt;NodeJS Essentials | Free E-Book&lt;/a&gt;


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

          &lt;a href="/adnanbabakan" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adnanbabakan" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Adnan Babakan (he/him)
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Adnan Babakan (he/him)
                
              
              &lt;div id="story-author-preview-content-453379" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adnanbabakan" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Adnan Babakan (he/him)&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 11 '20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" id="article-link-453379"&gt;
          NodeJS Essentials | Free E-Book
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/books"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;books&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;64&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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


&lt;/div&gt;





&lt;p&gt;Feel free to contact me if you have any questions, projects or suggestions to improve this article.&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Design a Multilingual Database Structure | A Practical Guide</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sat, 18 Oct 2025 13:34:44 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/how-to-design-a-multilingual-database-structure-a-practical-guide-35nf</link>
      <guid>https://dev.to/adnanbabakan/how-to-design-a-multilingual-database-structure-a-practical-guide-35nf</guid>
      <description>&lt;p&gt;Hi there, DEV.to community!&lt;/p&gt;

&lt;p&gt;Designing a database is a pleasurable task. It is where you limit the computers in how they should manage data. What each data means and what can be done with the combinations of them.&lt;/p&gt;

&lt;p&gt;I've enjoyed designing a multilingual database structure that can translate any entity in the database. And by translating, the action of storing translation records is meant, not translating them.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is the problem?
&lt;/h1&gt;

&lt;p&gt;The problem arises from wanting to have everything translatable in my back-end. And the number of languages varies as well. So there is a need to design such a structure that can accept many kinds of data as a translation target, like strings, numbers and even complex (non-primitive) objects like JSON data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Relational or Non-relational
&lt;/h1&gt;

&lt;p&gt;As you know, relational databases can have relations between their records, such as the relation of a foreign key to a primary key. And in non-relational databases, this cannot happen, not at least in their vanilla (bare) form.&lt;br&gt;
Whilst I designed this database in MySQL (MariaDB), there is no limitation in which database software you use, regardless of whether it is RDBMS or non-relational.&lt;/p&gt;
&lt;h1&gt;
  
  
  What is required
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Knowledge of how databases and ORM/ODM work&lt;/li&gt;
&lt;li&gt;A database engine running&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  A background of what we want
&lt;/h1&gt;

&lt;p&gt;What we want to achieve is a database that can store translatable data, regardless of its data type (at least as much as we can). As we know, foreign keys in relational databases can only relate to a single table. But we might have multiple tables, such as posts, products, couriers, and so many more. Here is when we are introduced to a thing called morphic relations. These kinds of relations are usually managed through a logical back-end.&lt;/p&gt;

&lt;p&gt;How we may create such a thing, you might ask. The answer depends on the approach we choose and can vary based on the mindset of the programmer. But there are two ways we may do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of having a simple foreign table ID relation, we can have two columns named &lt;code&gt;morphic_table&lt;/code&gt; and &lt;code&gt;morphic_id&lt;/code&gt;. Storing the name of the target table and the ID of the related record, respectively.&lt;/li&gt;
&lt;li&gt;Store both the target table and target ID in a column named &lt;code&gt;morphic_relation&lt;/code&gt; or something similar. Although this is against the best practices when designing a database, it proves to be super handy. The issue arises from the data we want to store not being atomic (meaning only one thing), but rather giving us two pieces of information. Where to look, and what to find. This structure is not unusual if you think of vector values. Thus, we may create our column as a text/string column and store our data with a simple delimiter. For instance, &lt;code&gt;table:id&lt;/code&gt;. So our data would become something like &lt;code&gt;posts:1243&lt;/code&gt; or &lt;code&gt;products:88214&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  The Languages Table
&lt;/h1&gt;

&lt;p&gt;The first thing we want is the languages table. This is where we will store the languages and their related data.&lt;br&gt;
Here is how I designed my languages table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enum direction {
  "rtl"
  "ltr"
}

Table languages {
  id primary unique
  iso_code string unique
  local_name string
  latin_name string
  direction direction
  calendar_system string
  font string
  font_feature_settings string
  is_default boolean
  is_active boolean
  created_at datetime
  updated_at datetime
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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



&lt;p&gt;&lt;em&gt;I am using &lt;a href="https://dbdiagram.io" rel="noopener noreferrer"&gt;dbdiagram.io&lt;/a&gt; to draw the database diagrams.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the explanation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: Primary ID of the record. I used CUID2 as my ID generation method, but the type ID can be anything and is irrelevant.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iso_code&lt;/code&gt;: A unique code that represents a language. I found IETF BCP 47 to be a good reference to distinguish every language. For instance &lt;code&gt;fa-IR&lt;/code&gt;, &lt;code&gt;en-US&lt;/code&gt;, or &lt;code&gt;es-ES&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;local_name&lt;/code&gt;: Name of the language written in its local form. Such as &lt;code&gt;فارسی&lt;/code&gt;, &lt;code&gt;English&lt;/code&gt; or &lt;code&gt;Español&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;latin_name&lt;/code&gt;: Name of the language written in Latin form. For instance, &lt;code&gt;Persian&lt;/code&gt;, &lt;code&gt;English&lt;/code&gt; or &lt;code&gt;Spanish&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;direction&lt;/code&gt;: Indicating the direction of a language's written form. Having only two options, being &lt;code&gt;RTL&lt;/code&gt; and &lt;code&gt;LTR&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;calendar_system&lt;/code&gt;: Indicating the calendar system associated with a language. Such as &lt;code&gt;Jalali&lt;/code&gt; or &lt;code&gt;Gregorian&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;font&lt;/code&gt;: Font used for the interface in the given language.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;font_feature_settings&lt;/code&gt;: Used to configure how the given font behaves in different conditions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_default&lt;/code&gt;: A boolean indicating whether the language is the default or not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_active&lt;/code&gt;: A boolean indicating if the language is active or not.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;created_at&lt;/code&gt;: Creation timestamp&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updated_at&lt;/code&gt;: Last update timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the columns indicated above are optional, as you can design your &lt;code&gt;languages&lt;/code&gt; table with only two columns being &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;iso_code&lt;/code&gt;. But having extra details can come in handy later on. The scope of using those additional data is beyond this article and you are at liberty to discover them on your own.&lt;/p&gt;
&lt;h1&gt;
  
  
  The language records table
&lt;/h1&gt;

&lt;p&gt;We want to make our database translatable no matter what our data are and how they are stored. To demonstrate such a structure, let's have a table called &lt;code&gt;language_records&lt;/code&gt; which will store data for each table and each piece of data we need. Here is the structure after designing that table:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enum direction {
  "rtl"
  "ltr"
}

Table languages {
  id primary unique
  iso_code string unique
  local_name string
  latin_name string
  direction direction
  calendar_system string
  font string
  font_feature_settings string
  is_default boolean
  is_active boolean
  created_at datetime
  updated_at datetime
}

Table language_records {
  id primary unique
  language_id string [ref: &amp;gt; languages.id]
  morphic_table string
  morphic_id string
  key string
  value string
  created_at datetime
  updated_at datetime
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sa63wz2h3dxxzzlabyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5sa63wz2h3dxxzzlabyr.png" alt="Language Records Table"&gt;&lt;/a&gt;&lt;/p&gt;
Demonstration of the language records table



&lt;p&gt;As you can see, I have added two simple columns named &lt;code&gt;morphic_table&lt;/code&gt; and &lt;code&gt;morphic_id&lt;/code&gt; to store which table to refer to and what row is wanted, respectively.&lt;/p&gt;

&lt;p&gt;Another approach to such a need, as mentioned before, is to have a single column to store both data and get out of being atomic. Here is the second kind of table:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enum direction {
  "rtl"
  "ltr"
}

Table languages {
  id primary unique
  iso_code string unique
  local_name string
  latin_name string
  direction direction
  calendar_system string
  font string
  font_feature_settings string
  is_default boolean
  is_active boolean
  created_at datetime
  updated_at datetime
}

Table language_records {
  id primary unique
  language_id string [ref: &amp;gt; languages.id]
  morphic_relation string
  key string
  value string
  created_at datetime
  updated_at datetime
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro9inm1w3jg6gicepv3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro9inm1w3jg6gicepv3a.png" alt="Language Records Table"&gt;&lt;/a&gt;&lt;/p&gt;
Demonstration of the language records table



&lt;p&gt;As you may have noticed, neither of the two structures above has any relation to any table other than the languages table. The relation to the entities themselves (such as &lt;code&gt;posts&lt;/code&gt; or &lt;code&gt;products&lt;/code&gt;) will be an abstract relation, meaning that we will handle them programmatically, and there is no need for the database to handle such a relation.&lt;/p&gt;

&lt;p&gt;I will go forward with both approaches so you may choose what fits your needs the best.&lt;/p&gt;
&lt;h1&gt;
  
  
  Entities to be translated
&lt;/h1&gt;

&lt;p&gt;Let's assume that we have two tables called &lt;code&gt;posts&lt;/code&gt; and &lt;code&gt;products&lt;/code&gt; that we want to have translatable fields in. A &lt;code&gt;post&lt;/code&gt; has &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt;, and a &lt;code&gt;product&lt;/code&gt; has &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;short_description&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the table structure for both tables:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Table posts {
  id primary unique
  created_at datetime
  updated_at datetime
}

Table products {
  id primary unique
  price double
  created_at datetime
  updated_at datetime
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;I won't be digging down the structure to a proper &lt;code&gt;post&lt;/code&gt; and &lt;code&gt;product&lt;/code&gt; build. As it is non-relevant in this article.&lt;/em&gt;&lt;/p&gt;

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



&lt;p&gt;You may notice that neither the &lt;code&gt;posts&lt;/code&gt; table has columns named &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt;, nor the &lt;code&gt;products&lt;/code&gt; table has columns named &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;short_description&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These data are abstract and will be controller and generated programmatically. You are free to implement how to store these data on your back-end. What I suggest to do is to have a mixin or a similar implementation based on your programming language.&lt;/p&gt;
&lt;h1&gt;
  
  
  Storing Language Records
&lt;/h1&gt;

&lt;p&gt;Now that we have our structures ready we may simply create our language and their relevant data according to our entities (being &lt;code&gt;posts&lt;/code&gt; and &lt;code&gt;products&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here is a simple data for our &lt;code&gt;languages&lt;/code&gt; table (I have omitted extra data due to them being irrelevant here):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;iso_code&lt;/th&gt;
&lt;th&gt;local_name&lt;/th&gt;
&lt;th&gt;latin_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;fa-IR&lt;/td&gt;
&lt;td&gt;فارسی&lt;/td&gt;
&lt;td&gt;Persian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;en-US&lt;/td&gt;
&lt;td&gt;English&lt;/td&gt;
&lt;td&gt;English&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;es-ES&lt;/td&gt;
&lt;td&gt;Español&lt;/td&gt;
&lt;td&gt;Spanish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now let's have a post added to our database:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And one product:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;39.99&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And that's it. It might seem strange but bear with me as it will make sense later on.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; column in our &lt;code&gt;language_records&lt;/code&gt; table will represent the data key related to our entity being &lt;code&gt;post&lt;/code&gt; or &lt;code&gt;product&lt;/code&gt; and the value will store its content.&lt;/p&gt;

&lt;p&gt;Now let's populate the language records table to represent the data needed to complete our first post and product.&lt;/p&gt;

&lt;p&gt;Here is the structure using &lt;code&gt;morphic_table&lt;/code&gt; and &lt;code&gt;morphic_id&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;language_id&lt;/th&gt;
&lt;th&gt;morphic_table&lt;/th&gt;
&lt;th&gt;morphic_id&lt;/th&gt;
&lt;th&gt;key&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;سلام دنیا&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Hello World&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Hola!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;آزمایشی&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;posts&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Testing in Spanish!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;محصول جدید&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Product in Spanish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;توضیح محصول&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Product Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;products&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Product Description in Spanish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And here is the same table using only a colum named &lt;code&gt;morphic_relation&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;id&lt;/th&gt;
&lt;th&gt;language_id&lt;/th&gt;
&lt;th&gt;morphic_realtion&lt;/th&gt;
&lt;th&gt;key&lt;/th&gt;
&lt;th&gt;value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;سلام دنیا&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Hello World&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;Hola!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;آزمایشی&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Testing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;posts:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Testing in Spanish!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;محصول جدید&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Product&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;Product in Spanish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;توضیح محصول&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Product Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;products:1&lt;/td&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Product Description in Spanish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Seeing the table above, we can conclude that we can fetch each language record for all of our data. And access translatable data based on different entities and different languages.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__hidden-navigation-link"&gt;NodeJS Essentials | Free E-Book&lt;/a&gt;


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

          &lt;a href="/adnanbabakan" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/adnanbabakan" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Adnan Babakan (he/him)
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Adnan Babakan (he/him)
                
              
              &lt;div id="story-author-preview-content-453379" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/adnanbabakan" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Adnan Babakan (he/him)&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 11 '20&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" id="article-link-453379"&gt;
          NodeJS Essentials | Free E-Book
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/node"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;node&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/books"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;books&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;64&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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


&lt;/div&gt;





&lt;p&gt;Feel free to contact me if you have any questions, projects or suggestions to improve this article.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>programming</category>
    </item>
    <item>
      <title>Doubly Linked List Implementation in Go</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sun, 06 Oct 2024 12:44:59 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/doubly-linked-list-implementation-in-go-4d47</link>
      <guid>https://dev.to/adnanbabakan/doubly-linked-list-implementation-in-go-4d47</guid>
      <description>&lt;p&gt;Hi there DEV.to community!&lt;/p&gt;

&lt;p&gt;As a second part of my previous post (linked in the series above), here we will implement a doubly linked list. A doubly linked list is just as a singly linked list with one difference. Each node refers to both its next node and its previous node. Thus we may move forward in the list using a function called &lt;code&gt;GetNext&lt;/code&gt; and move to the previous node with a function called &lt;code&gt;GetPrev&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzaf7birvs6hcxuylbns.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzaf7birvs6hcxuylbns.webp" alt="Doublye linked list" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;
Image source: GeeksforGeeks



&lt;p&gt;Before we start here is the structure I'd like to organize my codes like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project
├── doubly_linked_list
│   ├── node.go
│   └── list.go
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Doubly Node
&lt;/h1&gt;

&lt;p&gt;To define a doubly node in Go, the first thing we need to do is creating a struct in the &lt;code&gt;node.go&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DoublyNode&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;
    &lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A doubly node holds three properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;data&lt;/code&gt; property with &lt;code&gt;interface{}&lt;/code&gt; type so it can hold any data type&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;next&lt;/code&gt; property that holds a pointer to another &lt;code&gt;DoublyNode&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;prev&lt;/code&gt; property that holds a pointer to another &lt;code&gt;DoublyNode&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just as before we need to have some functions to utilize this struct. The first function we will define is a constructor that creates a new &lt;code&gt;DoublyNode&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDoublyNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&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 function creates a &lt;code&gt;DoublyNode&lt;/code&gt; and returns its reference.&lt;/p&gt;

&lt;p&gt;Then we will define setters and getters for all the properties (&lt;code&gt;data&lt;/code&gt;, &lt;code&gt;next&lt;/code&gt; and &lt;code&gt;prev&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNext&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;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"no next node"&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetPrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prev&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetPrev&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;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"no previous node"&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is the explanation for each function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SetData(data interface{})&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Receives a &lt;code&gt;data&lt;/code&gt; argument of &lt;code&gt;interface{}&lt;/code&gt; type and sets it as the &lt;code&gt;data&lt;/code&gt; of the node.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetData&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Returns the &lt;code&gt;data&lt;/code&gt; of the node&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SetNext(next *DoublyNode)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Receives a reference to node and sets it as the current node's &lt;code&gt;next&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Getnext()&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Check if the &lt;code&gt;next&lt;/code&gt; property of the node is nil to return an error,&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;next&lt;/code&gt; property is not nil, it returns the &lt;code&gt;next&lt;/code&gt; property of the node.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SetPrev(next *DoublyNode)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Receives a reference to node and sets it as the current node's &lt;code&gt;prev&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetPrev()&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Check if the &lt;code&gt;prev&lt;/code&gt; property of the node is nil to return an error,&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;prev&lt;/code&gt; property is not nil, it returns the &lt;code&gt;prev&lt;/code&gt; property of the node.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And my beloved &lt;code&gt;ToString&lt;/code&gt; function to make sure each time I know how to retrieve the data of the node as a string:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&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;h1&gt;
  
  
  List
&lt;/h1&gt;

&lt;p&gt;Now that we have our node defined it is time to define the list itself. I would put these codes inside the &lt;code&gt;list.go&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;head&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;
    &lt;span class="n"&gt;last&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="kt"&gt;int&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;code&gt;DoublyLinkedList&lt;/code&gt; is no different than the &lt;code&gt;SinglyLinkedList&lt;/code&gt; from the previous post. A doubly linked list usually differs in its node's structure.&lt;/p&gt;

&lt;p&gt;This struct holds up 3 properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;head&lt;/code&gt; to hold the first node of the list&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;last&lt;/code&gt; to hold the last node of the list&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;count&lt;/code&gt; to hold the number of nodes added inside the list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the functions that we need to utilize the struct.&lt;/p&gt;

&lt;p&gt;The first one as always is the function to create a new doubly linked list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewDoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&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 the most important function to attach a node to our list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AttachNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyNode&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetPrev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&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 function receives a node and checks if the list's head is empty adds it as the head of the list and if not sets the next of the last node in the list as the received node and sets the received node's prev as the current last node in the list.&lt;/p&gt;

&lt;p&gt;Then finally sets the last node of the list as the received node and increases the count of the list by one.&lt;/p&gt;

&lt;p&gt;I will a function (just as before) to receive a &lt;code&gt;data&lt;/code&gt; argument and turn it into a node and send it to the &lt;code&gt;AttachNode&lt;/code&gt; function so it becomes a little easier to add nodes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttachNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewDoublyNode&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A function to return the count of the list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you've read the previous article you know that I like to create functions named after the accessors of the &lt;code&gt;next&lt;/code&gt; and &lt;code&gt;prev&lt;/code&gt; of the nodes inside the list so it becomes a bit more consistent when accessing the data inside list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNext&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;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list is empty"&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetPrev&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;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list is empty"&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;code&gt;GetNext&lt;/code&gt; function checks if the &lt;code&gt;head&lt;/code&gt; is nil inside the list to return an error. And if not returns the first node of the list.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GetPrev&lt;/code&gt; function checks if the &lt;code&gt;last&lt;/code&gt; is nil inside the list to return an error. And if not returns the last node of the list.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;GetByIndex&lt;/code&gt; function is always recommended to make it possible to access the nodes by their index inside the list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetByIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="kt"&gt;int&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;DoublyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list is empty"&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="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index out of range"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&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="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function checks if the head is nil to return an error. Then checks if the &lt;code&gt;index+1&lt;/code&gt; is bigger than the count of the list to return an error since we consider the indices starting from 0.&lt;/p&gt;

&lt;p&gt;Then set the head of the list as &lt;code&gt;node&lt;/code&gt; and loop for 1 less than the provided the index so it moves forward as intended by replacing the node as the current node's &lt;code&gt;next&lt;/code&gt;. Finally returns the node with no error.&lt;/p&gt;
&lt;h1&gt;
  
  
  Testing
&lt;/h1&gt;

&lt;p&gt;To test the just written code you may do so in your main function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;doubly_linked_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"One"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Two"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Four"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;getBackToFirst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetPrev&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getBackToFirst&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// One&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or by using the &lt;code&gt;GetByIndex&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;doubly_linked_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDoublyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"One"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Two"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Four"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetByIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// Four&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>go</category>
      <category>datastructures</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Singly Linked List Implementation in Go</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sat, 05 Oct 2024 23:24:15 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/singly-linked-list-implementation-in-go-480o</link>
      <guid>https://dev.to/adnanbabakan/singly-linked-list-implementation-in-go-480o</guid>
      <description>&lt;p&gt;Hey there DEV.to community!&lt;/p&gt;

&lt;p&gt;This is a part of my data structures and algorithms series. In this article, we will implement a singly linked list then in the next articles from this series I will implement other kinds of linked lists as well using Go.&lt;/p&gt;

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



&lt;p&gt;To implement a singly linked list we need to structures, a node and a singly linked list itself. But before beginning to code here is how I like to organize my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;project
├── singly_linked_list
│   ├── node.go
│   └── list.go
└── main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Node
&lt;/h1&gt;

&lt;p&gt;A node only holds data and a pointer to the next node in its simplest form. Thus here is the struct we are going to use as a node (in the &lt;code&gt;node.go&lt;/code&gt; file):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SinglyNode&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We are using &lt;code&gt;interface{}&lt;/code&gt; as the data type for &lt;code&gt;data&lt;/code&gt; in the struct so we may store any data we want inside the node.&lt;/p&gt;

&lt;p&gt;Then we should define some methods to utilize the node struct we've just created.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewSinglyNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;data&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;If you are used to object-oriented languages you are mostly likely to be familiar with what a constructor is. Since Go is not an object-oriented language there are no classes but by some conventions around the Go world, we usually create a function prefixed with the word &lt;code&gt;New&lt;/code&gt;. But keep in mind that in the OOP languages &lt;code&gt;new&lt;/code&gt; is a special keyword that means creating an object. Here the &lt;code&gt;New&lt;/code&gt; is just a name prefix and nothing more.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NewSinglyNode&lt;/code&gt; function receives only one argument called &lt;code&gt;data&lt;/code&gt; with &lt;code&gt;interface{}&lt;/code&gt; type and returns a pointer of &lt;code&gt;SinglyNode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, we define some getters and setters for the node:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;interface&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNext&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;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"no next node"&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="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&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;code&gt;SetData&lt;/code&gt;, &lt;code&gt;Setnext&lt;/code&gt; and &lt;code&gt;GetData&lt;/code&gt; are pretty much self-explanatory. The &lt;code&gt;GetNext&lt;/code&gt; returns two values, a pointer to the next &lt;code&gt;SinglyNode&lt;/code&gt; and an error if there is no next node.&lt;/p&gt;

&lt;p&gt;Here is an extra function I always like to add so I can always know how the string representation of my struct is:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&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;h1&gt;
  
  
  List
&lt;/h1&gt;

&lt;p&gt;Now that we are done with our node we should implement the list itself. A singly linked list holds the first node as &lt;code&gt;head&lt;/code&gt; and as for my own preference two more data called &lt;code&gt;last&lt;/code&gt; holds the last node and a &lt;code&gt;country&lt;/code&gt; property that holds the count of the nodes added to the list.&lt;/p&gt;

&lt;p&gt;So here is the first lines of the &lt;code&gt;list.go&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;head&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;
    &lt;span class="n"&gt;last&lt;/span&gt;  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And obviously, a constructor-like function to create a &lt;code&gt;SinglyLinkedList&lt;/code&gt; with ease:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewSinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&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 most important function in a linked list is the one that adds a node. Here is my implementation of such a function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;AttachNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyNode&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetNext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&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 function does as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the head of the linked list is empty, if so set the received node as the head of the list.&lt;/li&gt;
&lt;li&gt;If the head is not empty it sets the received node as the &lt;code&gt;next&lt;/code&gt; property of the last node.&lt;/li&gt;
&lt;li&gt;Regardless of what happened before, the current node should be last node so the next time a node gets added it can get set as the next for the last node in our list.&lt;/li&gt;
&lt;li&gt;Increase the count by one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a function that receives data and creates a node and passes it to the &lt;code&gt;AttachNode&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AttachNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NewSinglyNode&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Although this function might seem redundant, it will ease adding nodes to the list without manually creating one each time.&lt;/p&gt;

&lt;p&gt;A function to get the count property as well:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&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 function needed is a function that should return the next node in the linked list:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetNext&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;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list is empty"&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I prefer to name this function as same as the &lt;code&gt;GetNext&lt;/code&gt; function defined for the nodes. This is done so there is more consistency. When first accessing a linked list the type is a linked list so there is no access to functions defined for nodes. Defining a function with the same name will make you able to use &lt;code&gt;GetNext&lt;/code&gt; as much as you want to traverse your list.&lt;/p&gt;

&lt;p&gt;One extra function that I always tend to add is a function to retrieve a node by the index:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;SinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetByIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="kt"&gt;int&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;SinglyNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&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="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"list is empty"&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="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index out of range"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&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="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function does as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the head is empty to return an error&lt;/li&gt;
&lt;li&gt;Check if &lt;code&gt;index+1&lt;/code&gt; is greater than the count of the list to return an error. We check for &lt;code&gt;index+1&lt;/code&gt; and not for &lt;code&gt;index&lt;/code&gt; since we consider the indices starting from 0 just like arrays.&lt;/li&gt;
&lt;li&gt;Assign &lt;code&gt;l.GetNext()&lt;/code&gt; to a variable named node (ignoring the error with &lt;code&gt;_&lt;/code&gt;) then loop for one less than the index provided as we already have the first one stored in the &lt;code&gt;node&lt;/code&gt; variable, assigning the next node of the current node as &lt;code&gt;node&lt;/code&gt; again.&lt;/li&gt;
&lt;li&gt;Return the traversed node without an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Testing
&lt;/h1&gt;

&lt;p&gt;Now that we have our linked list and node definitions, we can test it in our &lt;code&gt;main.go&lt;/code&gt; file just as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;singly_linked_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"One"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Two"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;firstNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;secondNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;firstNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;thirdNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;secondNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetNext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c"&gt;// One&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secondNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// Two&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thirdNode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  &lt;span class="c"&gt;// Three&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or using the &lt;code&gt;GetByIndex&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;singly_linked_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewSinglyLinkedList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"One"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Two"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Three"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetByIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c"&gt;// Three&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>go</category>
      <category>datastructures</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>More Secure JWT | A Better Experience</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sat, 05 Oct 2024 17:01:34 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/more-secure-jwt-a-better-experience-16nm</link>
      <guid>https://dev.to/adnanbabakan/more-secure-jwt-a-better-experience-16nm</guid>
      <description>&lt;p&gt;Hi there DEV.to community!&lt;/p&gt;

&lt;p&gt;Recently I've read some small posts on my social media that pointed out many security vulnerabilities of JWT. And the article below caught my eye.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/safdarali" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1351472%2F115e25ba-1733-4356-bf0c-1e5eff57b72f.jpeg" alt="safdarali"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/safdarali/why-do-many-people-not-recommend-using-jwt-1ol5" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Why Do Many People Not Recommend Using JWT?&lt;/h2&gt;
      &lt;h3&gt;Safdar Ali ・ Oct 3 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#hacktoberfest&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;The article above is a great one to tell you what might be the problem with using JWT as your main authentication method.&lt;/p&gt;

&lt;p&gt;Whilst many things mentioned in the article above are valid, there is a workaround for them. I personally suggest you switch to other token types if you are just starting your project. For instance, I usually use Laravel Sanctum when my back-end is Laravel. But if you have a project that is already using JWT and there is no possibility to simply change the token type or you are simply enjoying JWT and willing to manoeuvre I encourage you to read this article.&lt;/p&gt;

&lt;p&gt;I am taking an approach to counter the points declared in the article I linked above and might add some other points as well. In the end, you might suggest that what we have accomplished is not JWT anymore and you would be right in some way. Yet we should keep in mind that JWT doesn't enforce any structure to be put in the header or the payload and it only recommends them. You can refer to &lt;a href="https://jwt.io/introduction" rel="noopener noreferrer"&gt;here&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h1&gt;
  
  
  JWT size is big
&lt;/h1&gt;

&lt;p&gt;As you know a JWT consists of 3 parts: &lt;em&gt;header&lt;/em&gt;, &lt;em&gt;payload&lt;/em&gt; and &lt;em&gt;signature&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The header in a JWT usually consists of two properties. A &lt;code&gt;typ&lt;/code&gt; that is set to &lt;code&gt;JWT&lt;/code&gt; and &lt;code&gt;alg&lt;/code&gt; holds the algorithm type your signature is hashed with.&lt;/p&gt;

&lt;p&gt;For instance:&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;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&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;p&gt;If you are using multiple tokens for your system it is necessary to define these properties in your header so you may validate the token. But if your system isn't that big regarding the authentication types you might at least omit the &lt;code&gt;typ&lt;/code&gt; property to reduce a small size.&lt;/p&gt;

&lt;p&gt;A body can consist of anything you want to make use of your token. What I usually put inside a payload is the &lt;code&gt;id&lt;/code&gt; of the user who the token is issued for.&lt;/p&gt;

&lt;p&gt;The signature is a combination of your token's header and payload that is hashed.&lt;/p&gt;

&lt;p&gt;Here are some symmetric hash algorithms you may use according to the JWT website:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Algorithm&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HS256&lt;/td&gt;
&lt;td&gt;32 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HS384&lt;/td&gt;
&lt;td&gt;48 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HS512&lt;/td&gt;
&lt;td&gt;64 bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you want more security you may use asymmetric algorithms as well. Symmetric algorithms are still fine for most small use cases though.&lt;/p&gt;

&lt;p&gt;So choosing a smaller size for the signature can reduce your token size overall. You might argue that HS256 is less secure than HS384 and HS512 respectively! While it is true, you should consider that each bit can be represented in two ways, a &lt;code&gt;0&lt;/code&gt; or a &lt;code&gt;1&lt;/code&gt;. Thus, a 256-bit (32-byte) signature is one in &lt;code&gt;115,792,089,237,316,195,423,570,985,008,687,907,853,269,984,665,640,564,039,457,584,007,913,129,639,936&lt;/code&gt; possibility. So if you are trying to use a 384-bit or a 512-bit signature without having a valid reason you are just wasting space.&lt;/p&gt;

&lt;p&gt;With all these changes we can compare a predefined JWT to a custom JWT we've just made in size.&lt;/p&gt;

&lt;p&gt;Note that we are using the same payload for both tokens:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456"&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;p&gt;Here is the token with the default header and using HS512 algorithm for signature:&lt;br&gt;
Header:&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;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS512"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&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;p&gt;Token:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEyMzQ1NiJ9.Kvwu-9rwEgar8j6OH8HN57Vj5DQKYWDi-H9tfTWV3-TawrxIv_Wc_WLfTDNJeA3W9-omQhvi8xbZCacLEzMqQw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And now the custom-made token that omits the &lt;code&gt;typ&lt;/code&gt; in header and uses the HS256 to have the signature hashed.&lt;br&gt;
Header:&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;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HS256"&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;p&gt;Token:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEyMzQ1NiJ9.mT15OKTKJMODj5xHKTmTTq9i8dqJ_b1-C1pY7RbDvRI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Comparing the size of both tokens we can see that the first token is 144 bytes long and the second one which we customized a bit is 85 bytes long. It is about 40% smaller.&lt;/p&gt;
&lt;h1&gt;
  
  
  Revocation of the tokens and security issues
&lt;/h1&gt;

&lt;p&gt;So far we know that JWT is a stateless token that doesn't need a server to hold the information for use as the token already carries the necessary data. This brings up a problem! You cannot revoke a JWT that simply.&lt;/p&gt;

&lt;p&gt;But it is not the end of the world and there are some techniques we may put in use to circumvent this issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8w6u839huhi9q6lm07d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8w6u839huhi9q6lm07d.webp" alt="One does not simply" width="500" height="280"&gt;&lt;/a&gt;&lt;/p&gt;
One does not simply revoke a JWT! (or centre a div.)


&lt;h2&gt;
  
  
  Token blacklisting
&lt;/h2&gt;

&lt;p&gt;Blacklisting a token is a simple way you might consider. To blacklist a token you can assign an id to each token in your payload and blacklist it in your database (or any kind of storage) so the token is considered invalid.&lt;/p&gt;

&lt;p&gt;My personal way of doing so is assigning a UUID/ULID for each token inside the payload like this:&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;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"token_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"348087cf-8d57-4318-ac46-051c8ffd1ba5"&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;p&gt;Some suggest to store the whole token and consider it invalid, but it raises two problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your token doesn't have a dynamic part like a issue date or an id to identify the token uniquely you might blacklist all the tokens for a user no matter when they are created, meanwhile blacklisting every token that will be created in the future.&lt;/li&gt;
&lt;li&gt;Storing a whole token in your database takes up a lot of space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this technique is good to implement it defeats one of the main purposes of a JWT which is being stateless. So this makes your tokens a hybrid regarding the stateful/stateless matter.&lt;/p&gt;
&lt;h2&gt;
  
  
  Token expiration time
&lt;/h2&gt;

&lt;p&gt;Adding an expiration time to your payload can be beneficial in two ways. First point is that your tokens will be more secure if they are stolen there is a finite time the token can be used and the second is the revoking problem which can be solved with a short lifespan for the token. This approach also maintains the statelessness of the token.&lt;/p&gt;

&lt;p&gt;Here is an example:&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;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1728146311"&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;p&gt;There are some caveats for this method as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a token has a long expiration time it defeats the purpose of the expiration time.&lt;/li&gt;
&lt;li&gt;With shorter expiration time you need to implement a structure in which users can refresh their tokens to maintain their identity with your system, hence adding more complexity on your side.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Issue number of the token
&lt;/h2&gt;

&lt;p&gt;This can be interpreted as the opposite of blacklisting a token. In this method, you can have an issue number for each token and store the latest token issue number along with the users details in database. For instance, when issuing the first token the token issue number for a user can include number 1. You may issue multiple tokens with this issue number and increase the number by one when you want to invalidate the previous token or tokens. As you might have guessed this can be problematic since you cannot simply revoke only one token and you need to revoke every token issued with that issue number.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are more secure ways that are more complex than what you've read here to revoke a JWT that is beyond the scope of this article.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Security issues
&lt;/h1&gt;

&lt;p&gt;A JWT's header and payload are base64 encoded, which makes them possible to see the raw content with simply decoding it. This can raise security issues of people knowing the secrets of a user if they access their token(s).&lt;/p&gt;

&lt;p&gt;Such a case is avoidable in few ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never store sensitive data inside the payload and only store the data needed to verify who the claimer is.&lt;/li&gt;
&lt;li&gt;Encrypt the data stored inside the payload which you can decrypt yourself on the back-end.&lt;/li&gt;
&lt;li&gt;As always make sure you are using a secure connection such as HTTPS for web/mobile applications.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Feel free to let me know if I am missing anything or if I made a mistake. Hope this article was useful for you.
&lt;/h2&gt;

&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jwt</category>
      <category>security</category>
    </item>
    <item>
      <title>Vue 3 | Cheat Sheet of The Dark Side | Part 1 | Reactivity</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Tue, 01 Oct 2024 22:50:56 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/vue-3-cheat-sheet-of-the-dark-side-part-1-reactivity-5a89</link>
      <guid>https://dev.to/adnanbabakan/vue-3-cheat-sheet-of-the-dark-side-part-1-reactivity-5a89</guid>
      <description>&lt;p&gt;Hi there DEV.to community!&lt;/p&gt;

&lt;p&gt;This article will include multiple aspects of Vue 3 that are mostly used or are kind of on the dark side and not paid attention to as they are supposed to.&lt;/p&gt;

&lt;p&gt;As I am going to describe Vue 3, I am going to use the composition API and not the old-school options API. The concept of both methods are same so you can adapt to composition API pretty quickly. I am in no place to dictate anything and every programmer is free to choose the way they want to write their program but as a personal opinion, I prefer composition API for its concise syntax and better code management. So if you are still afraid to change to composition API I suggest you give it a shot as it will be worth it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6v6hyj8syyf2sevsdld.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6v6hyj8syyf2sevsdld.webp" alt="DARK SIDE!!!!" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;
This is how you will feel after reading this article. I hope :).



&lt;h1&gt;
  
  
  Table of Content
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
Reactivity

&lt;ul&gt;
&lt;li&gt;Ref&lt;/li&gt;
&lt;li&gt;Reactive&lt;/li&gt;
&lt;li&gt;Shallow Ref&lt;/li&gt;
&lt;li&gt;Shallow Reactive&lt;/li&gt;
&lt;li&gt;Shallow Reactive&lt;/li&gt;
&lt;li&gt;Readonly&lt;/li&gt;
&lt;li&gt;Shallow Read Only&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Computed

&lt;ul&gt;
&lt;li&gt;Writable Computed&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Watching

&lt;ul&gt;
&lt;li&gt;
Watch

&lt;ul&gt;
&lt;li&gt;Immediate&lt;/li&gt;
&lt;li&gt;Once&lt;/li&gt;
&lt;li&gt;Watching Getter Function&lt;/li&gt;
&lt;li&gt;Watching Multiple Values&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Watch Effect&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Reactivity &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;React isn't the only one that should come to mind when we talk about reactivity. Reactivity refers to the ability of an entity (given a webpage) to react based on the data changes. You might know this concept as MVVM. MVVM is the abbreviated form of Model-View-View-Model. As the name suggests when data changes the view changes and vice-versa.&lt;/p&gt;

&lt;p&gt;To utilize the reactivity power of Vue there are some options that we are going cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ref &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You can think of a &lt;code&gt;ref&lt;/code&gt; as a special kind of variable that you can use inside your Vue application. This description is only true when you start working with Vue for the first time as it gets a bit more complex afterwards.&lt;/p&gt;

&lt;p&gt;Defining a ref is as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Use it inside your template using the interpolation syntax:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;{{ message }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you are asking yourself why I called it a variable but declared &lt;code&gt;message&lt;/code&gt; using a &lt;code&gt;const&lt;/code&gt; keyword you have the every right to.&lt;/p&gt;

&lt;p&gt;As you know you cannot change the value of constant, as it is the purpose of the &lt;code&gt;const&lt;/code&gt; keyword. But there is subtle little thing you should know about. Although the keyword &lt;code&gt;const&lt;/code&gt; doesn't let the data of a variable to be changed, it doesn't care about the nested data! This is the case with &lt;code&gt;ref&lt;/code&gt; as well. To understand this situation better try the code below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;a&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="na"&gt;b&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="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see I can change the value of &lt;code&gt;o.a&lt;/code&gt; since objects are only references and not a whole value by themselves. So when I change the value of &lt;code&gt;a&lt;/code&gt; inside the object &lt;code&gt;o&lt;/code&gt; the &lt;code&gt;const&lt;/code&gt; limitation isn't applied. Of course, if you wanted to assign a value to &lt;code&gt;o&lt;/code&gt; itself it will throw an error and won't let you do it. For example, the code below is wrong:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;a&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="na"&gt;b&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="na"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the same case when using &lt;code&gt;ref&lt;/code&gt; (and other stuff you will see later here). When you invoke a &lt;code&gt;ref&lt;/code&gt; function it turns everything it received into an object. This is called wrapping. Try this code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see something like the image below:&lt;/p&gt;

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

&lt;p&gt;As you can see when logging the &lt;code&gt;message&lt;/code&gt; variable you are not receiving &lt;code&gt;Hello World&lt;/code&gt; directly, instead it is inside an object and you can access your actual value using the &lt;code&gt;value&lt;/code&gt; key of the aforementioned object. This lets Vue watch for changes and do the MVVM thing! :)&lt;/p&gt;

&lt;p&gt;When you access your ref inside a Vue template there is no need to access it like &lt;code&gt;message.value&lt;/code&gt;. Vue is smart enough to render the actual value inside the template instead of the object. But in case you want to access or modify the value of a ref inside your script you should do so using &lt;code&gt;.value&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Adnan!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Adnan!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Reactive &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As you've seen when using a &lt;code&gt;ref&lt;/code&gt;, Vue wraps your data inside an object and lets you access it via &lt;code&gt;.value&lt;/code&gt;. This is usually the most used case. You can wrap almost everything using a &lt;code&gt;ref&lt;/code&gt; and make it reactive.&lt;/p&gt;

&lt;p&gt;In case you wonder how Vue watches for value changes and renders the view again and again, you should check out &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" rel="noopener noreferrer"&gt;JavaScript Proxies&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If your value is an object itself, then you can use &lt;code&gt;reactive&lt;/code&gt; instead of &lt;code&gt;ref&lt;/code&gt;. The &lt;code&gt;reactive&lt;/code&gt; function won't wrap your value and instead will make the object itself reactive and watchable.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;count&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you try to print out the &lt;code&gt;o&lt;/code&gt; constant you will see that it is indeed your object without any major changes:&lt;/p&gt;

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

&lt;p&gt;Now you may manipulate the key &lt;code&gt;count&lt;/code&gt; as you would normally do in JavaScript and Vue will render the changes as soon as possible.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increase&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you had &lt;code&gt;ref&lt;/code&gt; instead of &lt;code&gt;reactive&lt;/code&gt; it would have looked like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;count&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increase&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you are still unsure which one to use, keep in mind that &lt;code&gt;ref&lt;/code&gt; is a safe option to use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shallow Ref &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Give that you have a &lt;code&gt;ref&lt;/code&gt; like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&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;And printed my last name in your template as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;{{ state.names.adnan }}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you every changed my last name like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adnan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;masruri&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Your template will be updated to show &lt;code&gt;masruri&lt;/code&gt; instead of &lt;code&gt;babakan&lt;/code&gt;. This is due to the fact that &lt;code&gt;ref&lt;/code&gt; makes a deeply watched object and the changes to the view (template) are triggered for nested data as well.&lt;/p&gt;

&lt;p&gt;There is an option to prevent such behaviour if that's what you want. To do so you may use &lt;code&gt;shallowRef&lt;/code&gt;. A &lt;code&gt;shallowRef&lt;/code&gt; acts exactly like &lt;code&gt;ref&lt;/code&gt; does, with an exception of not watching for deep changes.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adnan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;masruri&lt;/span&gt;&lt;span class="dl"&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 code above will result in your template showing &lt;code&gt;babakan&lt;/code&gt; as it is not watched. But changing the &lt;code&gt;.value&lt;/code&gt; entirely will trigger changes. So the code below will result in your template getting updated as well:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;masruri&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&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 is a great option for performance-related concerns.&lt;/p&gt;
&lt;h2&gt;
  
  
  Shallow Reactive &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So far we've known that &lt;code&gt;ref&lt;/code&gt; wraps the data and watches it deeply and &lt;code&gt;shallowRef&lt;/code&gt; wraps the data and watches it shallowly. Now tell me this, if &lt;code&gt;reactive&lt;/code&gt; makes an object reactive, what does &lt;code&gt;shallowReactive&lt;/code&gt; do?&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowReactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adnan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;masruri&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you might have guessed the template won't be updated.&lt;/p&gt;
&lt;h2&gt;
  
  
  Trigger Ref &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given that you are using a &lt;code&gt;shallowRef&lt;/code&gt; and changed a value and now want your template to be updated according to the new data as well, you may use the &lt;code&gt;triggerRef&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowRef&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;adnan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arian&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amini&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mahdi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;salehi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adnan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;masruri&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nf"&gt;triggerRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&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 the template will also show &lt;code&gt;masruri&lt;/code&gt;. This is more like changing from an automatic gear to a manual gear if you will.&lt;/p&gt;

&lt;p&gt;This is usable for both &lt;code&gt;shallowRef&lt;/code&gt; and &lt;code&gt;shallowReactive&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Read Only &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;readonly&lt;/code&gt; function receives a &lt;code&gt;ref&lt;/code&gt; or a &lt;code&gt;reactive&lt;/code&gt; as an argument and returns an exact copy that is only possible to be read from. This is used when you want to make sure your data is safe and is not possible to change when watching for it.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&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="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;infoReadOnly&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;infoReadOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arian&lt;/span&gt;&lt;span class="dl"&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="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Though I've changed the value of &lt;code&gt;info&lt;/code&gt;, since &lt;code&gt;infoReadOnly&lt;/code&gt; is actually a live copy of &lt;code&gt;info&lt;/code&gt; my changes are reflected in &lt;code&gt;infoReadOnly&lt;/code&gt; as well. Yet you may not change the values using &lt;code&gt;infoReadOnly&lt;/code&gt; directly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;infoReadOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readonly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;infoReadOnly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arian&lt;/span&gt;&lt;span class="dl"&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 won't change the data and will warn you in the console as below:&lt;/p&gt;

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

&lt;p&gt;If we have &lt;code&gt;ref&lt;/code&gt; and &lt;code&gt;shallowRef&lt;/code&gt;, &lt;code&gt;reactive&lt;/code&gt; and &lt;code&gt;shallowReactive&lt;/code&gt;, why not have a &lt;code&gt;shallowReadonly&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;shallowReadonly&lt;/code&gt; only makes the root level elements &lt;code&gt;readonly&lt;/code&gt; whilst you can change the nested data:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stateShallowReadonly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowReadonly&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;friends&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ata&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mahdi&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stateShallowReadonly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brad&lt;/span&gt;&lt;span class="dl"&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 code above will warn you and won't change the value of &lt;code&gt;name&lt;/code&gt; since it is a direct property.&lt;/p&gt;

&lt;p&gt;But you can freely change anything inside &lt;code&gt;friends&lt;/code&gt; since it is nested:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stateShallowReadonly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallowReadonly&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;friends&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Arian&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ata&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mahdi&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stateShallowReadonly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;friends&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="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Brad&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Computed &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Man, I love computed in Vue! You can imagine it as a glass in which you can mix your potions and still have your potions standing there intact!&lt;/p&gt;

&lt;p&gt;A computed is like a &lt;code&gt;ref&lt;/code&gt; or &lt;code&gt;reactive&lt;/code&gt; that can be accessed and watched but not changed. Then what's the difference between a computed and a readonly you might ask. A computed can be a mixture of stuff. For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you have a &lt;code&gt;fullName&lt;/code&gt; which you may access its value inside a template with &lt;code&gt;{{ fullName }}&lt;/code&gt; or inside your script using &lt;code&gt;fullName.value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The value of &lt;code&gt;fullName&lt;/code&gt; will always depend on the &lt;code&gt;state.value.first&lt;/code&gt; and &lt;code&gt;state.value.last&lt;/code&gt; and will change if those guys change.&lt;/p&gt;

&lt;p&gt;A computed receives a function that returns a value and can depend on multiple reactive data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writable Computed &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Though a computed is mostly used to read a combination of data, the possibility to make a computed writable is also there.&lt;/p&gt;

&lt;p&gt;Instead of passing a function to computed you may pass an object including two properties called &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; that both are functions.&lt;/p&gt;

&lt;p&gt;For instance:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adnan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;last&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Babakan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;get&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;last&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 if you try to write the value of &lt;code&gt;fullName&lt;/code&gt; like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ata Parvin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will split your string into 2 parts using a space and assign the first part to &lt;code&gt;state.value.first&lt;/code&gt; and the second to &lt;code&gt;state.value.last&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is not a good way to determine which part of a name is a first name and which is a last name, but for the sake of demonstration, this is the only thing that came to my mind. :D&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Watching &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Watching is something that you will probably need a lot. Watching is referred to the act in which you want to run something in case a reactive data changes. In different systems there are various naming for this act, sometimes they are called hooks as well. But in Vue, we will call them watches.&lt;/p&gt;
&lt;h2&gt;
  
  
  Watch &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The first thing you will encounter. A &lt;code&gt;watch&lt;/code&gt; function receives two arguments. The reactive data to watch and the function to be invoked when the data changes respectively.&lt;/p&gt;

&lt;p&gt;Here is a simple watch:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increase&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Count changed to &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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 whenever the value of &lt;code&gt;count&lt;/code&gt; is changed, you will see the log &lt;code&gt;Count changed to ((count))&lt;/code&gt; in your console.&lt;/p&gt;

&lt;p&gt;The callback function also receives two arguments which are passed to it when the watch is triggered. The first argument holds the new value and the second one holds the old value. Here is an example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increase&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Counter changed from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;oldValue&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; to &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;newValue&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;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; Be careful when using the &lt;code&gt;newValue&lt;/code&gt; and &lt;code&gt;oldValue&lt;/code&gt; with objects as objects are passed by reference.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To be more accurate, a &lt;code&gt;watch&lt;/code&gt; function receives a third argument as well. This third argument is an object that holds some options which can change the behaviour of the watching action.&lt;/p&gt;
&lt;h3&gt;
  
  
  Immediate &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;An immediate watch function is triggered at the instance it's created as well as when a change happens. You can think of it as the difference between a &lt;code&gt;while&lt;/code&gt; loop and a &lt;code&gt;do...while&lt;/code&gt; loop if you know what I mean. In other words, even if there is never a change, your callback function will run at least once:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Count changed to &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="na"&gt;immediate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The value for &lt;code&gt;immediate&lt;/code&gt; can be &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;. And the default value is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Once &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;If you want your watcher to run only once, you may define the &lt;code&gt;once&lt;/code&gt; option and set its value to &lt;code&gt;true&lt;/code&gt;. The default value is &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Count changed to &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="na"&gt;once&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will only trigger once when the value of &lt;code&gt;count&lt;/code&gt; changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Advanced Watchers &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Previously we've mentioned that watchers accept a reactive data as the first argument. While this is true, this is not the whole case.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;watch&lt;/code&gt; function can receive a getter function or an array of reactive objects and getter functions. This is used for when we need to watch for multiple data changes, and/or when we need to watch the result of two or more things when affecting each other. Let's have some examples.&lt;/p&gt;
&lt;h3&gt;
  
  
  Watching Getter Function &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Take the code below as an example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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;Timer one: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;timerOne&lt;/span&gt; &lt;span class="si"&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;Timer two: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;timerTwo&lt;/span&gt; &lt;span class="si"&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;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"timerOne++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Accelerate timer one&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"timerTwo++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Accelerate timer two&lt;span class="nt"&gt;&amp;lt;/button&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;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timerOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timerTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&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;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;timerOne&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="nx"&gt;timerTwo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;timerOne&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;timerTwo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;There was a change in the gap between timerOne and timerTwo. Gap is &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timerOne&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;timerTwo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; seconds.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;It's a simple code that makes 2 refs holding a number and increasing both of them 1 by 1 each second. Logically the difference of these two refs are always equal to zero unless one gets changes out of its turn. As both increase the difference stays 0 so the watched won't get triggered as it only watches for the changes to the result of &lt;code&gt;timerOne.value - timerTwo.value&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Yet there are two buttons that each adds 1 to &lt;code&gt;timerOne&lt;/code&gt; and &lt;code&gt;timerTwo&lt;/code&gt; respectively. When you click on any of those buttons the difference will be more or less than 0 thus the watch being triggered and logging the gap between these two timers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Watching Multiple Values &lt;a&gt;
&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Here is an example of an array of reactive data being passed to the first argument of the &lt;code&gt;watch&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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;Counter one: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;counterOne&lt;/span&gt; &lt;span class="si"&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;Counter two: &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;counterTwo&lt;/span&gt; &lt;span class="si"&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;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"counterOne++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Increase counter one&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"counterTwo++"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Increase counter two&lt;span class="nt"&gt;&amp;lt;/button&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;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counterTwo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;counterOne&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;counterTwo&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;One of the counters changes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;No matter which ref changes, the watcher will be triggered.&lt;/p&gt;
&lt;h2&gt;
  
  
  Watch Effect &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;watchEffect&lt;/code&gt; function acts almost exactly like a &lt;code&gt;watch&lt;/code&gt; function with a main difference. In a &lt;code&gt;watchEffect&lt;/code&gt; you don't need to define what to watch and any reactive data that is used inside the callback you provide your &lt;code&gt;watchEffect&lt;/code&gt; is watched automatically. For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="nf"&gt;watchEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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 case our &lt;code&gt;count&lt;/code&gt; is changed the &lt;code&gt;watchEffect&lt;/code&gt; will trigger its callback function since &lt;code&gt;count.value&lt;/code&gt; is used inside it. This is good if you have complex logic to watch for.&lt;/p&gt;



&lt;p&gt;Hope this was useful and you've enjoyed it. In case you spot any mistakes or feel like there should be an improvement, kindly let me know.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Serving a Static Website in Ubuntu [NGINX + Docker]</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sat, 28 Sep 2024 17:15:19 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/serving-a-static-website-in-ubuntu-nginx-docker-1no6</link>
      <guid>https://dev.to/adnanbabakan/serving-a-static-website-in-ubuntu-nginx-docker-1no6</guid>
      <description>&lt;p&gt;Hi there DEV.to community.&lt;/p&gt;

&lt;p&gt;Recently as I was working on a personal project I was looking for a simple deployment of a static website on my Ubuntu server using Docker. Although it is possible to serve a simple static website using only nginx, this article will let you know about the principles of hosting a website using Docker which you can expand as you wish.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prerequisities
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu server installed (I am using Ubuntu 22.04)&lt;/li&gt;
&lt;li&gt;Docker installed (If you need help with installing Docker here is a good article from DigitalOcean: &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04" rel="noopener noreferrer"&gt;How To Install and Use Docker on Ubuntu 22.04&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Making our website ready
&lt;/h1&gt;

&lt;p&gt;Nowadays there are two main website types. First is the one rendered using a back-end service such as Laravel or Nuxt called SSR websites. And second is the websites that are pre-rendered (referred to as a &lt;code&gt;generated&lt;/code&gt; website as well). The pre-rendered websites can be categorized into two sections, a classic website which includes a &lt;code&gt;.html&lt;/code&gt; file for each page, and a SPA which usually directs all requests to your &lt;code&gt;index.html&lt;/code&gt; and your JavaScript router engages to respond with the appropriate page to be shown.&lt;/p&gt;

&lt;p&gt;Here we will discuss SPA apps only that redirect all the request to your &lt;code&gt;index.html&lt;/code&gt;. These types of generations are usually possible using the build tools inside your framework. For instance a Nuxt project can be generated for static deployment using &lt;code&gt;npm run generate&lt;/code&gt; and puts the output inside your &lt;code&gt;.output/public&lt;/code&gt; directory.&lt;/p&gt;

&lt;h1&gt;
  
  
  Preparing the Dockerfile
&lt;/h1&gt;

&lt;p&gt;We should first create a file called &lt;code&gt;Dockerfile&lt;/code&gt; at the root of our project.&lt;/p&gt;

&lt;p&gt;We are going to use &lt;code&gt;nginx:alpine&lt;/code&gt; image since it is lightweight and does whatever we want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we should determine the config of our nginx. To do so first of all I prefer to remove the default config file to make sure the new data is loaded correctly:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; /etc/nginx/conf.d/default.conf

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"server {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              listen 80;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              root /usr/share/nginx/html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              index index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location / {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  try_files &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt;/ /index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location ~* &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  expires 30d;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  access_log off;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location ~ /&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;ht {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  deny  all;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              error_page 404 /index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;          }"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nginx/conf.d/default.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This section deletes the &lt;code&gt;/etc/nginx/conf.d/default.conf&lt;/code&gt; file and writes the new data in the same file (and creating it since it doesn't exist anymore). The backslashes (&lt;code&gt;\&lt;/code&gt;) are added to the end of each line since it is interpreted as a string and we need to make sure new lines are considered inside of the string and not our dockerfile. This is called an escape character.&lt;/p&gt;

&lt;p&gt;Let's analyze what this Nginx config does:&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;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This line tells Nginx to listen on port 80. This port is exposed inside the container when it is running and we should bind it to an external port with which we can access the web server with our server's IP. So this 80 has nothing to do with which port the application will be accessible through.&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;root&lt;/span&gt; &lt;span class="n"&gt;/usr/share/nginx/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This line declares the directory in which we store our website's files.&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;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This line determines the index of website. Index of a website is the file that is loaded when no address is provided with the request.&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;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;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="n"&gt;/index.html&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 block redirects all the requests to the &lt;code&gt;index.html&lt;/code&gt;. So using this config assures us that the rest of the routing is handled by our JavaScript framework's router and not by the webserver all through.&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;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)&lt;/span&gt;$ &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;expires&lt;/span&gt; &lt;span class="s"&gt;30d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="kn"&gt;access_log&lt;/span&gt; &lt;span class="no"&gt;off&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 block tells the browser requesting the file types indicated to cache them for 30 days.&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;location&lt;/span&gt; &lt;span class="p"&gt;~&lt;/span&gt; &lt;span class="sr"&gt;/\.ht&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kn"&gt;deny&lt;/span&gt;  &lt;span class="s"&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 block denies direct access to files with a format starting with &lt;code&gt;.ht&lt;/code&gt;. This includes &lt;code&gt;.html&lt;/code&gt; and &lt;code&gt;.htm&lt;/code&gt; files.&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;error_page&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt; &lt;span class="n"&gt;/index.html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And at the end, we redirect 404 errors to our &lt;code&gt;index.html&lt;/code&gt; as well so that your beautiful error page can be shown by your framework.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; .output/public /usr/share/nginx/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code above will be the last line in our Dockerfile. It copies the content of your generated website inside &lt;code&gt;/usr/share/ngnix/html&lt;/code&gt; directory of the container that will run.&lt;/p&gt;

&lt;p&gt;So here is the full Dockefile:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; /etc/nginx/conf.d/default.conf

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"server {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              listen 80;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              root /usr/share/nginx/html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              index index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location / {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  try_files &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt;/ /index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location ~* &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  expires 30d;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  access_log off;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              location ~ /&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;ht {&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;                  deny  all;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              }&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;              error_page 404 /index.html;&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;          }"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nginx/conf.d/default.conf

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; .output/public /usr/share/nginx/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Building and running
&lt;/h1&gt;

&lt;p&gt;There are two main ways to run this Docker project. One is manually and the other one uses a &lt;code&gt;compose.yml&lt;/code&gt; file. Here ae both:&lt;/p&gt;
&lt;h2&gt;
  
  
  Manually
&lt;/h2&gt;

&lt;p&gt;First we need to build the image. Run the command below in your terminal of choosing at the root of your project:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-static-website &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;docker build&lt;/code&gt; is the command that builds your image for you. The &lt;code&gt;-t&lt;/code&gt; flag sets a name for your image so you can replace &lt;code&gt;my-static-website&lt;/code&gt; with anything you want. And finally &lt;code&gt;.&lt;/code&gt; indicates the folder including your Dockerfile which is the current folder. If you ever wanted to run this command from another folder you need to put the absolute address of your projects root instead of &lt;code&gt;.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It might take a few seconds (or minutes) to build you image. The output of the command above should look like this:&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="o"&gt;[&lt;/span&gt;+] Building 36.7s &lt;span class="o"&gt;(&lt;/span&gt;9/9&lt;span class="o"&gt;)&lt;/span&gt; FINISHED                                                                                                 docker:default
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;internal] load build definition from Dockerfile                                                                                        0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; transferring dockerfile: 686B                                                                                                        0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;internal] load metadata &lt;span class="k"&gt;for &lt;/span&gt;docker.io/library/nginx:alpine                                                                             0.4s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;internal] load .dockerignore                                                                                                           0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; transferring context: 2B                                                                                                             0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;1/4] FROM docker.io/library/nginx:alpine@sha256:a5127daff3d6f4606be3100a252419bfa84fd6ee5cd74d0feaca1a5068f97dcf                      15.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; resolve docker.io/library/nginx:alpine@sha256:a5127daff3d6f4606be3100a252419bfa84fd6ee5cd74d0feaca1a5068f97dcf                       0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:b887aca7aed6134b029401507d27ac9c8fbfc5a6cf510d254bdf4ac841cf1552 11.21kB / 11.21kB                                            0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:af676cbe1eebad012784df0b450beb143af153514b61986d262cfae62f83335d 1.79MB / 1.79MB                                              4.2s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:cf04c63912e16506c4413937c7f4579018e4bb25c272d989789cfba77b12f951 4.09MB / 4.09MB                                              4.4s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:0bd499aae1693a481ec5f38cefa5f8803e0d8a5bef0c20cb3e6989eb2975cde9 627B / 627B                                                  1.2s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:a5127daff3d6f4606be3100a252419bfa84fd6ee5cd74d0feaca1a5068f97dcf 9.07kB / 9.07kB                                              0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:19db381c08a95b2040d5637a65c7a59af6c2f21444b0c8730505280a0255fb53 2.50kB / 2.50kB                                              0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:a258ad06a688beff3d4a30eede1b350e64a9ebbd5b80b8a095eec17f3f5a9e15 956B / 956B                                                  2.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:906b4c822d155ab6595749cb264093152af7faafabdc0d5534fb161909cf71b4 394B / 394B                                                  2.9s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:780210e97849521bfdd49e752a71a1e150219ee398e1bd8c6399e7d8797b923f 1.21kB / 1.21kB                                              3.7s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:45d5bc49ce25a46e0fa4f1481ae38f289d8f5f6b207ff03d038bcb784afe821e 1.40kB / 1.40kB                                              4.5s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; sha256:f12230e24af8b61e0b5f5e6c066fe0cfd975bac104a495a9e8fa28dc513c271f 13.72MB / 13.72MB                                           14.6s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:cf04c63912e16506c4413937c7f4579018e4bb25c272d989789cfba77b12f951                                                   0.1s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:af676cbe1eebad012784df0b450beb143af153514b61986d262cfae62f83335d                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:0bd499aae1693a481ec5f38cefa5f8803e0d8a5bef0c20cb3e6989eb2975cde9                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:a258ad06a688beff3d4a30eede1b350e64a9ebbd5b80b8a095eec17f3f5a9e15                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:906b4c822d155ab6595749cb264093152af7faafabdc0d5534fb161909cf71b4                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:780210e97849521bfdd49e752a71a1e150219ee398e1bd8c6399e7d8797b923f                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:45d5bc49ce25a46e0fa4f1481ae38f289d8f5f6b207ff03d038bcb784afe821e                                                   0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; extracting sha256:f12230e24af8b61e0b5f5e6c066fe0cfd975bac104a495a9e8fa28dc513c271f                                                   0.3s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;internal] load build context                                                                                                           0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; transferring context: 3.25kB                                                                                                         0.0s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;2/4] RUN &lt;span class="nb"&gt;rm&lt;/span&gt; /etc/nginx/conf.d/default.conf                                                                                            20.8s
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;3/4] RUN &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"server {              listen 80;              root /usr/share/nginx/html;              index index.html;                0.3s
 =&amp;gt; [4/4] COPY .output/public /usr/share/nginx/html                                                                                                      0.1s
 =&amp;gt; exporting to image                                                                                                                      0.0s
 =&amp;gt; =&amp;gt; exporting layers                                                                                                                     0.0s
 =&amp;gt; =&amp;gt; writing image sha256:f8842f2b4cbf232c6b7139efe2e348e13a12188a58e60ef1f767a635c341de26                                                0.0s
 =&amp;gt; =&amp;gt; naming to docker.io/library/my-static-website 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can run the command below to see the list of your images:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see your image in the list as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-static-website   latest    f8842f2b4cbf   About a minute ago   62.2MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that we have our image ready it is time to run it. To run it we can use the command below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"4000:80"&lt;/span&gt; my-static-website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;docker run&lt;/code&gt; command tries to run the image you provided. Here we added to flags which are as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; tells docker to run the container in detached mode. Detached mode is when the process is run in background and doesn't need your terminal session to stay open.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p&lt;/code&gt; flag which receives an argument with &lt;code&gt;HOST:CONTAINER&lt;/code&gt; format binds your container's innerly exposed port to a port on your actual host machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can see the list of your running containers using the command below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see a record like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;e7a66fd934c1   my-static-website   &lt;span class="s2"&gt;"/docker-entrypoint.…"&lt;/span&gt;   3 seconds ago   Up 2 seconds   0.0.0.0:4000-&amp;gt;80/tcp, :::4000-&amp;gt;80/tcp   quirky_keller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can access your website using &lt;code&gt;IP:4000&lt;/code&gt;. &lt;code&gt;IP&lt;/code&gt; is the IP of the machine docker running on. Or &lt;code&gt;127.0.0.1:4000&lt;/code&gt; if you are experimenting on your own machine.&lt;/p&gt;

&lt;p&gt;If running a container as above satisfies your needs then we are done here. But I am going to show you how to set a domain on your project so you can access it using a domain instead of an IP.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using docker composer
&lt;/h2&gt;

&lt;p&gt;Usage of a compose file is super neat and makes your life easier. You can imagine it as a set of premade commands and instructions for your docker. Create a file named &lt;code&gt;compse.yml&lt;/code&gt; and put the content below in it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;my-static-website&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
            &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can relate probably, these settings are somehow counterparts of the commands that we've run manually.&lt;/p&gt;

&lt;p&gt;Inside the services, we define our service called &lt;code&gt;my-static-website&lt;/code&gt; and let docker know how to build it using our Dockerfile. And we've bound out ports as well just as we did when running the &lt;code&gt;docker run&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Now that you have this file the only command you need to run is:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command builds and runs your image and container respectively just as we've done it manually. And thanks to the &lt;code&gt;-d&lt;/code&gt; (flag of detachment) the running process moved to the background.&lt;/p&gt;
&lt;h1&gt;
  
  
  Setting a domain
&lt;/h1&gt;

&lt;p&gt;To set a domain we need to run an Nginx instance on the machine we've deployed the container itself. This makes us able to have a reverse proxy that directs incoming HTTP requests which use port 80 to another port and sends back the response to the user.&lt;/p&gt;

&lt;p&gt;Installing Nginx on Ubuntu is fairly simple:&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 &lt;span class="nb"&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the installation is complete make sure to allow Nginx in your firewall:&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;ufw allow &lt;span class="s1"&gt;'Nginx HTTP'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This opens ports 80 and 443 for HTTP and HTTPS respectively.&lt;/p&gt;

&lt;p&gt;Nginx uses a structure that is easy to control available sites and enabled sites. To make a site enabled it is usually recommended to create a file following the websites domain inside the &lt;code&gt;/etc/nginx/sites-available&lt;/code&gt; directory. So first of all move inside this 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;cd&lt;/span&gt; /etc/nginx/sites-available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we need to make a file named after the domain. Although it is not mandated to be the domain name, following this practice makes it easier to maintain your configuration files. You may create the file using the &lt;code&gt;touch&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;mydomain.com.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or simple using a text editor to open the file (in case the file doesn't exist it will create it upon saving). I prefer &lt;code&gt;nano&lt;/code&gt; so here is how we do it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano mydomain.com.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Inside the editor paste the code below:&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;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;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:4000&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="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 break this configuration up:&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;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This tells Nginx to listen to port 80 for this server configuration.&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_name&lt;/span&gt; &lt;span class="s"&gt;mydomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This sets the active domains for this server configuration. You may use multiple domains here and put the &lt;code&gt;www.&lt;/code&gt; subdomain here as well in case you want it:&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_name&lt;/span&gt; &lt;span class="s"&gt;mydomain.com&lt;/span&gt; &lt;span class="s"&gt;www.mydomain.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The location scope in this configuration is:&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;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://127.0.0.1:4000&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the main part that redirects all the requests to your container. It passes every request to &lt;code&gt;127.0.0.1:4000&lt;/code&gt; along with all the parameters.&lt;/p&gt;

&lt;p&gt;Now save the file and make sure your file is saved correctly using the &lt;code&gt;ls&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-hla&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you see your file here then we are done here.&lt;/p&gt;

&lt;p&gt;Now it is time to link this file to the &lt;code&gt;/etc/nginx/sites-enabled&lt;/code&gt; directory which Nginx reads to serve websites:&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 ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/mydomain.com.conf /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now move to the enabled sites 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;cd&lt;/span&gt; /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Check if your file is linked in this 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;ls&lt;/span&gt; &lt;span class="nt"&gt;-hla&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see a record as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lrwxrwxrwx 1 root root   44 Sep 28 17:05 mydomain.com.conf -&amp;gt; /etc/nginx/sites-available/mydomain.com.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now it is time to reload your Nginx so your website comes alive:&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 reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If there are no errors in the configuration you've just created reloading the Nginx service won't output anything. So if you see no message you are done here as well.&lt;/p&gt;

&lt;p&gt;Now that our Nginx server waits for requests coming for &lt;code&gt;mydomain.com&lt;/code&gt; we need to point this domain to our server.&lt;/p&gt;

&lt;p&gt;If you are using a real domain and a real server you can use a DNS service such as Cloudflare and make an &lt;code&gt;A RECORD&lt;/code&gt; pointing your domain to your server's IP.&lt;/p&gt;

&lt;p&gt;In case you are just testing locally you may change your &lt;code&gt;hosts&lt;/code&gt; file to point your domain to your servers IP.&lt;/p&gt;

&lt;p&gt;Now accessing the &lt;code&gt;mydomain.com&lt;/code&gt; domain should show you your static website successfully!&lt;/p&gt;



&lt;p&gt;Hope you've found this article helpful. Feel free to let me know if there are any mistakes in the article or any points to make it better.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>docker</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Dockerizing Laravel (With compose) [Alpine + NGINX + PHP FPM + MariaDB + PHPMyAdmin] 🛳️🛳️</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Thu, 11 Jan 2024 14:07:40 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/dockerizing-laravel-with-compose-nginx-php-fpm-mariadb-phpmyadmin-8n1</link>
      <guid>https://dev.to/adnanbabakan/dockerizing-laravel-with-compose-nginx-php-fpm-mariadb-phpmyadmin-8n1</guid>
      <description>&lt;p&gt;Hey there DEV.to community!&lt;/p&gt;

&lt;p&gt;In the last part, we've covered how to dockerize a Laravel app. That was a great way to know how stuff goes around in a docker container and get you started before moving to the next level!&lt;/p&gt;

&lt;p&gt;Although it is possible to run all your requirements inside a single container it is not a great practice. (Thanks to &lt;a class="mentioned-user" href="https://dev.to/yuhenobi"&gt;@yuhenobi&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;In this part, we will go through a better-architectured solution using docker compose.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's a docker compose?
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services. Then, with a single command, you create and start all the services from your configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the definition of docker's compose tool by its official documentation. I believe it is the simplest description you'll find of it.&lt;/p&gt;

&lt;p&gt;But let me explain how docker compose can make your life easier.&lt;/p&gt;

&lt;p&gt;Imagine you want to run a nginx container to serve for your laravel app. The amount of arguments you have to put in can grow radically very fast very soon because you probably want to configure it to your needs.&lt;/p&gt;

&lt;p&gt;This is how a simple nginx container should start along with its volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; some-nginx &lt;span class="nt"&gt;-v&lt;/span&gt; /some/content:/usr/share/nginx/html:ro &lt;span class="nt"&gt;-d&lt;/span&gt; nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now imagine that you want to publish the port of your container to the host:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; nginx &lt;span class="nt"&gt;-v&lt;/span&gt; /nginx/html:/usr/share/nginx/html &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"8000:80"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the command grows bigger and bigger. It is hard to handle such commands and remembering all the options is pretty hard at times.&lt;/p&gt;

&lt;p&gt;Docker compose is a simple YAML file that you can store your configuration of how one or more containers should run and how they interact with each other and so on.&lt;/p&gt;

&lt;p&gt;So the composer configuration for the aforementioned command looks like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/nginx/html:/usr/share/nginx/html&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8000:80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Saving this configuration inside a file called &lt;code&gt;docker-compose.yml&lt;/code&gt; and running the command below will result in the same as before:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;The flag &lt;code&gt;-d&lt;/code&gt; stands for detached. It means send the process to the background when it's done. If you omit adding this flag the containers defined in the compose file will stop if you exit the process.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Laravel Dockerfile
&lt;/h1&gt;

&lt;p&gt;Before everything else we need to dockerize Laravel. I chose &lt;code&gt;php:8.2-fpm-alpine3.19&lt;/code&gt; as my base image since it has a small image size since it is based on alpine and fpm gives you the speed you need for your application!&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;Dockerfile.laravel&lt;/code&gt; and put the code below in it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.2-fpm-alpine3.19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_NAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_ENV&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_DEBUG&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_URL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_CHANNEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_DEPRECATIONS_CHANNEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_LEVEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_CONNECTION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_DATABASE&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_USERNAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_PASSWORD&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BROADCAST_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; CACHE_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; FILESYSTEM_DISK&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; QUEUE_CONNECTION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; SESSION_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; SESSION_LIFETIME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MEMCACHED_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; REDIS_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; REDIS_PASSWORD&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; REDIS_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_MAILER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_USERNAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_PASSWORD&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_ENCRYPTION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_FROM_ADDRESS&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; MAIL_FROM_NAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; AWS_ACCESS_KEY_ID&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; AWS_SECRET_ACCESS_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; AWS_DEFAULT_REGION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; AWS_BUCKET&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; AWS_USE_PATH_STYLE_ENDPOINT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_APP_ID&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_APP_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_APP_SECRET&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_SCHEME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; PUSHER_APP_CLUSTER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_APP_NAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_PUSHER_APP_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_PUSHER_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_PUSHER_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_PUSHER_SCHEME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; VITE_PUSHER_APP_CLUSTER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUCKET_ENDPOINT_URL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUCKET_ACCESS_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUCKET_SECRET_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUCKET_DEFAULT_REGION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BUCKET_NAME&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add php-session &lt;span class="se"&gt;\
&lt;/span&gt;    php-tokenizer &lt;span class="se"&gt;\
&lt;/span&gt;    php-xml &lt;span class="se"&gt;\
&lt;/span&gt;    php-ctype &lt;span class="se"&gt;\
&lt;/span&gt;    php-curl &lt;span class="se"&gt;\
&lt;/span&gt;    php-dom &lt;span class="se"&gt;\
&lt;/span&gt;    php-fileinfo &lt;span class="se"&gt;\
&lt;/span&gt;    php-mbstring &lt;span class="se"&gt;\
&lt;/span&gt;    php-openssl &lt;span class="se"&gt;\
&lt;/span&gt;    php-pdo &lt;span class="se"&gt;\
&lt;/span&gt;    php-pdo_mysql &lt;span class="se"&gt;\
&lt;/span&gt;    php-session &lt;span class="se"&gt;\
&lt;/span&gt;    php-tokenizer &lt;span class="se"&gt;\
&lt;/span&gt;    php-xml &lt;span class="se"&gt;\
&lt;/span&gt;    php-ctype &lt;span class="se"&gt;\
&lt;/span&gt;    php-xmlwriter &lt;span class="se"&gt;\
&lt;/span&gt;    php-simplexml &lt;span class="se"&gt;\
&lt;/span&gt;    composer


&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-install mysqli pdo_mysql
&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-enable mysqli pdo_mysql

&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--update&lt;/span&gt; nodejs npm

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /var/www/html&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www/html&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;APP_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$APP_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_ENV=&lt;/span&gt;&lt;span class="nv"&gt;$APP_ENV&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_DEBUG=&lt;/span&gt;&lt;span class="nv"&gt;$APP_DEBUG&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_URL=&lt;/span&gt;&lt;span class="nv"&gt;$APP_URL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_CHANNEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_CHANNEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_DEPRECATIONS_CHANNEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_DEPRECATIONS_CHANNEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_LEVEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_LEVEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_CONNECTION=&lt;/span&gt;&lt;span class="nv"&gt;$DB_CONNECTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_DATABASE=&lt;/span&gt;&lt;span class="nv"&gt;$DB_DATABASE&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_USERNAME=&lt;/span&gt;&lt;span class="nv"&gt;$DB_USERNAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BROADCAST_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$BROADCAST_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;CACHE_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$CACHE_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;FILESYSTEM_DISK=&lt;/span&gt;&lt;span class="nv"&gt;$FILESYSTEM_DISK&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;QUEUE_CONNECTION=&lt;/span&gt;&lt;span class="nv"&gt;$QUEUE_CONNECTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;SESSION_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$SESSION_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;SESSION_LIFETIME=&lt;/span&gt;&lt;span class="nv"&gt;$SESSION_LIFETIME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MEMCACHED_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$MEMCACHED_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_MAILER=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_MAILER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_USERNAME=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_USERNAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_ENCRYPTION=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_ENCRYPTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_FROM_ADDRESS=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_FROM_ADDRESS&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_FROM_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_FROM_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_ACCESS_KEY_ID=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_SECRET_ACCESS_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_DEFAULT_REGION=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_BUCKET=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_BUCKET&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_USE_PATH_STYLE_ENDPOINT=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_USE_PATH_STYLE_ENDPOINT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_ID=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_ID&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_SECRET=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_SECRET&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_SCHEME=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_SCHEME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_CLUSTER=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_CLUSTER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_APP_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_APP_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_SCHEME=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_SCHEME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_APP_CLUSTER=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_APP_CLUSTER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_ENDPOINT_URL=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_ENDPOINT_URL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_ACCESS_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_ACCESS_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_SECRET_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_SECRET_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_DEFAULT_REGION=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_DEFAULT_REGION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /usr/local/laravel.env

&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 9000&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;chmod -R o+w /var/www/html/storage&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;chown -R root:root /var/www/html/storage&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;cp /usr/local/laravel.env /var/www/html/.env&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;php-fpm&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /start.sh

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x &lt;span class="s2"&gt;"/start.sh"&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; "/start.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;When you need more than one Dockerfile the convention is to name it like &lt;code&gt;Dockerfile.[NAME]&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So let's dive into the Dockerfile and see what's happening.&lt;/p&gt;

&lt;p&gt;First of all, we define our base image:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;php:8.2-fpm-alpine3.19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then define the ARGs that we are going to use as our Laravel application's env.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_NAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_ENV&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_KEY&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_DEBUG&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; APP_URL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_CHANNEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_DEPRECATIONS_CHANNEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; LOG_LEVEL&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_CONNECTION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_HOST&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_PORT&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_DATABASE&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_USERNAME&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; DB_PASSWORD&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; BROADCAST_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; CACHE_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; FILESYSTEM_DISK&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; QUEUE_CONNECTION&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; SESSION_DRIVER&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; SESSION_LIFETIME&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After defining the base image and ARGs we need to install the requirements of Laravel so it can run on this container:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apk add php-session &lt;span class="se"&gt;\
&lt;/span&gt;    php-tokenizer &lt;span class="se"&gt;\
&lt;/span&gt;    php-xml &lt;span class="se"&gt;\
&lt;/span&gt;    php-ctype &lt;span class="se"&gt;\
&lt;/span&gt;    php-curl &lt;span class="se"&gt;\
&lt;/span&gt;    php-dom &lt;span class="se"&gt;\
&lt;/span&gt;    php-fileinfo &lt;span class="se"&gt;\
&lt;/span&gt;    php-mbstring &lt;span class="se"&gt;\
&lt;/span&gt;    php-openssl &lt;span class="se"&gt;\
&lt;/span&gt;    php-pdo &lt;span class="se"&gt;\
&lt;/span&gt;    php-pdo_mysql &lt;span class="se"&gt;\
&lt;/span&gt;    php-session &lt;span class="se"&gt;\
&lt;/span&gt;    php-tokenizer &lt;span class="se"&gt;\
&lt;/span&gt;    php-xml &lt;span class="se"&gt;\
&lt;/span&gt;    php-ctype &lt;span class="se"&gt;\
&lt;/span&gt;    php-xmlwriter &lt;span class="se"&gt;\
&lt;/span&gt;    php-simplexml &lt;span class="se"&gt;\
&lt;/span&gt;    composer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;I've omitted git and other tools that are not absolute requirements of Laravel but you can add them if you wish.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then using a great tool called &lt;code&gt;docker-php-ext-install&lt;/code&gt; which is already installed in the base image we chose, we enable MySQL extension:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-install mysqli pdo_mysql
&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-enable mysqli pdo_mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;To see the supported PHP extensions you can enable using &lt;code&gt;docker-php-ext-install&lt;/code&gt; visit &lt;a href="https://github.com/mlocati/docker-php-extension-installer?tab=readme-ov-file#supported-php-extensions" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Some Laravel apps need Node to run if you are using Laravel as a full-stack framework. So installing Node.js is a must:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--update&lt;/span&gt; nodejs npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then simply copy the current directory inside &lt;code&gt;/var/www/html&lt;/code&gt; and change the working directory as well:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /var/www/html&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Well, this part gets a little tricky but it is pretty simple. Since we are going to mount &lt;code&gt;/var/www/html&lt;/code&gt; as a volume to be shared between other containers, the data inside this directory cannot be changed while building the image and needs to be changed after the container has run. Thus, we need to create a &lt;code&gt;.env&lt;/code&gt; file and copy it into the Laravel directory later on:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;APP_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$APP_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_ENV=&lt;/span&gt;&lt;span class="nv"&gt;$APP_ENV&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_DEBUG=&lt;/span&gt;&lt;span class="nv"&gt;$APP_DEBUG&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;APP_URL=&lt;/span&gt;&lt;span class="nv"&gt;$APP_URL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_CHANNEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_CHANNEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_DEPRECATIONS_CHANNEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_DEPRECATIONS_CHANNEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;LOG_LEVEL=&lt;/span&gt;&lt;span class="nv"&gt;$LOG_LEVEL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_CONNECTION=&lt;/span&gt;&lt;span class="nv"&gt;$DB_CONNECTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$DB_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_DATABASE=&lt;/span&gt;&lt;span class="nv"&gt;$DB_DATABASE&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_USERNAME=&lt;/span&gt;&lt;span class="nv"&gt;$DB_USERNAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;DB_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$DB_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BROADCAST_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$BROADCAST_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;CACHE_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$CACHE_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;FILESYSTEM_DISK=&lt;/span&gt;&lt;span class="nv"&gt;$FILESYSTEM_DISK&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;QUEUE_CONNECTION=&lt;/span&gt;&lt;span class="nv"&gt;$QUEUE_CONNECTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;SESSION_DRIVER=&lt;/span&gt;&lt;span class="nv"&gt;$SESSION_DRIVER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;SESSION_LIFETIME=&lt;/span&gt;&lt;span class="nv"&gt;$SESSION_LIFETIME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MEMCACHED_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$MEMCACHED_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;REDIS_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$REDIS_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_MAILER=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_MAILER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_USERNAME=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_USERNAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_PASSWORD=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_PASSWORD&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_ENCRYPTION=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_ENCRYPTION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_FROM_ADDRESS=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_FROM_ADDRESS&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;MAIL_FROM_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$MAIL_FROM_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_ACCESS_KEY_ID=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_SECRET_ACCESS_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_DEFAULT_REGION=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_DEFAULT_REGION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_BUCKET=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_BUCKET&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;AWS_USE_PATH_STYLE_ENDPOINT=&lt;/span&gt;&lt;span class="nv"&gt;$AWS_USE_PATH_STYLE_ENDPOINT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_ID=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_ID&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_SECRET=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_SECRET&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_SCHEME=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_SCHEME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;PUSHER_APP_CLUSTER=&lt;/span&gt;&lt;span class="nv"&gt;$PUSHER_APP_CLUSTER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_APP_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_APP_NAME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_APP_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_APP_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_HOST=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_HOST&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_PORT=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_PORT&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_SCHEME=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_SCHEME&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;VITE_PUSHER_APP_CLUSTER=&lt;/span&gt;&lt;span class="nv"&gt;$VITE_PUSHER_APP_CLUSTER&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_ENDPOINT_URL=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_ENDPOINT_URL&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_ACCESS_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_ACCESS_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_SECRET_KEY=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_SECRET_KEY&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_DEFAULT_REGION=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_DEFAULT_REGION&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;BUCKET_NAME=&lt;/span&gt;&lt;span class="nv"&gt;$BUCKET_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /usr/local/laravel.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I've saved this file &lt;code&gt;/usr/local/laravel.env&lt;/code&gt; which will be used in our custom start-up script.&lt;/p&gt;

&lt;p&gt;Now it's time to install PHP and Node.js dependencies:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And expose port 9000. This port is used by PHP-FPM:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 9000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the next step we need to create a custom start-up script as bellow:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;chmod -R o+w /var/www/html/storage&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;chown -R root:root /var/www/html/storage&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;cp /usr/local/laravel.env /var/www/html/.env&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;php-fpm&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is done since only one command can be run inside a container and a container will stop when the command has been completed.&lt;/p&gt;

&lt;p&gt;Give the script permission to be executed:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x &lt;span class="s2"&gt;"/start.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And finally, set it as our entrypoint:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; "/start.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  NGINX Dockerfile
&lt;/h1&gt;

&lt;p&gt;We need some customization to run NGINX the way we need it.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;Dockerfile.nginx&lt;/code&gt; and put the code below in it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;nginx:stable-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    server {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        listen 80;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        index index.php index.html;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        error_log  /var/log/nginx/error.log;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        access_log /var/log/nginx/access.log;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        root /var/www/html/public;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location ~ &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;php&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            try_files &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri =404;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_split_path_info ^(.+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;php)(/.+)&lt;/span&gt;&lt;span class="nv"&gt;$;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_pass laravel:9000;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_index index.php;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            include fastcgi_params;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_param SCRIPT_FILENAME &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;document_root&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;fastcgi_script_name;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_param PATH_INFO &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;fastcgi_path_info;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location / {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            try_files &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri/ /index.php?&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;query_string;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            gzip_static on;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nginx/conf.d/default.conf

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This Dockerfile uses &lt;code&gt;FROM nginx:stable-alpine&lt;/code&gt; as its base image.&lt;/p&gt;

&lt;p&gt;We need to customize the way NGINX behaves to meet Laravel's requirements. The configuration that is saved inside &lt;code&gt;/etc/nginx/conf.d/default.conf&lt;/code&gt; is the configuration recommended by Laravel's official documentation with a few minor tweaks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changed the fast_cgi address to &lt;code&gt;laravel:9000&lt;/code&gt; which will be available inside a private network we will define late inside a &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Changed the root of our website to &lt;code&gt;/var/www/html/public&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Docker compose
&lt;/h1&gt;

&lt;p&gt;Now that we have our customized Laravel and NGINX images, it is time to define the relation of these images and a few more images.&lt;/p&gt;

&lt;p&gt;Create a file called &lt;code&gt;docker-compose.yml&lt;/code&gt; and put the code below in it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-laravel&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;laravel-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;laravel-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
  &lt;span class="na"&gt;laravel-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;laravel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
            &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile.laravel&lt;/span&gt;
            &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_NAME=Laravel&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_ENV=local&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_KEY=&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_DEBUG=true&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;APP_URL=YOUR_APP_URL&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LOG_CHANNEL=stack&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LOG_DEPRECATIONS_CHANNEL=null&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;LOG_LEVEL=debug&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_CONNECTION=mysql&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_HOST=db&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_PORT=3306&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_DATABASE=laravel&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_USERNAME=root&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DB_PASSWORD=DATABASE_PASSWORD&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;BROADCAST_DRIVER=log&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;CACHE_DRIVER=file&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FILESYSTEM_DISK=minio&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;QUEUE_CONNECTION=sync&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SESSION_DRIVER=file&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SESSION_LIFETIME=120&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MEMCACHED_HOST=127.0.0.1&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REDIS_HOST=127.0.0.1&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REDIS_PASSWORD=null&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REDIS_PORT=6379&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_MAILER=smtp&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_HOST=mailpit&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_PORT=1025&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_USERNAME=null&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_PASSWORD=null&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_ENCRYPTION=null&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_FROM_ADDRESS="hello@example.com"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MAIL_FROM_NAME="${APP_NAME}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;AWS_DEFAULT_REGION=us-east-1&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;AWS_USE_PATH_STYLE_ENDPOINT=false&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PUSHER_PORT=443&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PUSHER_SCHEME=https&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PUSHER_APP_CLUSTER=mt1&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_APP_NAME="${APP_NAME}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_PUSHER_HOST="${PUSHER_HOST}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_PUSHER_PORT="${PUSHER_PORT}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"&lt;/span&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-network&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-app:/var/www/html&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

    &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
            &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile.nginx&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-app:/var/www/html&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16005:80"&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-network&lt;/span&gt;

    &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mariadb&lt;/span&gt;
        &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-network&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DATABASE_PASSWORD&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
            &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DATABASE_PASSWORD&lt;/span&gt;
        &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-db:/var/lib/mysql&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

    &lt;span class="na"&gt;phpmyadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;phpmyadmin&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;16006:80"&lt;/span&gt;
        &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PMA_HOST=db&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PMA_PORT=3306&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;UPLOAD_LIMIT=50000000&lt;/span&gt;
        &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;laravel-network&lt;/span&gt;
        &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Change the configuration to your needs and run the command below to start your containers:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now you can access your Laravel app from &lt;code&gt;localhost:16005&lt;/code&gt; and your PhpMyAdmin from &lt;code&gt;localhost:16006&lt;/code&gt;.&lt;/p&gt;



&lt;p&gt;I hope this article was helpful. Please let me know of any mistakes or improvements.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dockerizing Laravel 10 [Ubuntu image + PHP 8.2 FPM + NGINX] 🛳️🛳️</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Sat, 23 Dec 2023 18:31:54 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/dockerizing-laravel-10-ubuntu-image-php-82-fpm-nginx-318p</link>
      <guid>https://dev.to/adnanbabakan/dockerizing-laravel-10-ubuntu-image-php-82-fpm-nginx-318p</guid>
      <description>&lt;p&gt;Hi there DEV.to community!&lt;/p&gt;

&lt;p&gt;I've been trying to dockerize my Laravel app which acts as an API and run it on my server. While many Dockerfile exists on the internet when you search, they are mostly incomplete or somehow specific to some usage.&lt;/p&gt;

&lt;p&gt;I will explain how I've done it and try to complete it to become a great Dockerfile for Laravel. Please let me know of anything better or any way to optimize it or any features missing from an optimal Laravel environment.&lt;/p&gt;

&lt;p&gt;Be aware that this article is only about dockerizing a Laravel application and not any other database or filesystem. I will put these as a series procedurally.&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;Copy the content below inside a file called Docerfile at the root of your project. (Root of a project is where there are files like &lt;code&gt;artisan&lt;/code&gt;, &lt;code&gt;composer.json&lt;/code&gt; and &lt;code&gt;.env&lt;/code&gt; , in case you are confused)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ubuntu:latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DEBIAN_FRONTEND noninteractive&lt;/span&gt;

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; software-properties-common
&lt;span class="k"&gt;RUN &lt;/span&gt;add-apt-repository &lt;span class="nt"&gt;-y&lt;/span&gt; ppa:ondrej/php
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; php8.2&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-cli&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-common&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-fpm&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-mysql&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-zip&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-gd&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-mbstring&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-curl&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-xml&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-bcmath&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-pdo

&lt;span class="c"&gt;# Install php-fpm&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; php8.2-fpm php8.2-cli

&lt;span class="c"&gt;# Install composer&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl
&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--install-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin &lt;span class="nt"&gt;--filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;composer

&lt;span class="c"&gt;# Install nodejs&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ca-certificates gnupg
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/apt/keyrings
&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/nodesource.gpg
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_MAJOR 20&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_&lt;/span&gt;&lt;span class="nv"&gt;$NODE_MAJOR&lt;/span&gt;&lt;span class="s2"&gt;.x nodistro main"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/nodesource.list
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs

&lt;span class="c"&gt;# Install nginx&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nginx
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    server {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        listen 80;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        listen [::]:80;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        root /var/www/html/public;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        add_header X-Frame-Options &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;SAMEORIGIN&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        add_header X-Content-Type-Options &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;nosniff&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        index index.php;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        charset utf-8;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location / {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            try_files &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri/ /index.php?&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;query_string;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location = /favicon.ico { access_log off; log_not_found off; }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location = /robots.txt  { access_log off; log_not_found off; }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        error_page 404 /index.php;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location ~ &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;php&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_pass unix:/run/php/php8.2-fpm.sock;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_param SCRIPT_FILENAME &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;realpath_root&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;fastcgi_script_name;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            include fastcgi_params;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location ~ /&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;(?!well-known).* {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            deny all;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nginx/sites-available/default

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    #!/bin/sh&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Starting services...&lt;/span&gt;&lt;span class="se"&gt;\"\n\
&lt;/span&gt;&lt;span class="s2"&gt;    service php8.2-fpm start&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    nginx -g &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;daemon off;&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Ready.&lt;/span&gt;&lt;span class="se"&gt;\"\n\
&lt;/span&gt;&lt;span class="s2"&gt;    tail -s 1 /var/log/nginx/*.log -f&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    "&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /start.sh

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /var/www/html&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www/html&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data /var/www/html

&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh", "/start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Run the build command from terminal and then run the image:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; MY_IMAGE &lt;span class="nb"&gt;.&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"8000:80"&lt;/span&gt; MY_IMAGE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then open your browser and navigate to "&lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;http://localhost:8000/&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;Boom! Your Laravel is up!&lt;/p&gt;
&lt;h1&gt;
  
  
  Dive deeper
&lt;/h1&gt;

&lt;p&gt;If you are in a hurry it is good to just copy/paste the codes above and get your job done. But if you want to know what is happening and how you can customize it based on your needs follow the article. You need a basic understanding of Docker though, so research about Docker for more detailed information.&lt;/p&gt;
&lt;h2&gt;
  
  
  Base image and stage
&lt;/h2&gt;

&lt;p&gt;In the first line, you can see this line:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ubuntu:latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;base&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This means that we are defining a stage of build called &lt;code&gt;base&lt;/code&gt; from the latest Ubuntu image.&lt;/p&gt;

&lt;p&gt;Follow the line mentioned above you see an environment variable being set:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DEBIAN_FRONTEND noninteractive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This sets Ubuntu's interface as a non-interactive one. This is done because some commands might ask for user input and since that is not possible to do so and we need our image to build as quickly and as easily as possible, we need to disable input prompts so it does not stop the build process.&lt;/p&gt;

&lt;p&gt;We need to update the packages of Ubuntu, hence the line:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Laravel dependencies
&lt;/h2&gt;

&lt;p&gt;Obviously, every program needs some stuff installed before running and Laravel is not an exception. If you follow the link to &lt;a href="https://laravel.com/docs/10.x/deployment" rel="noopener noreferrer"&gt;Laravel's official deployment documentation&lt;/a&gt; you can see the prerequisites to run Laravel.&lt;/p&gt;

&lt;p&gt;As Laravel's documentation mentions it needs PHP version 8.1 or higher. We will use PHP 8.2 along with the FPM to run Laravel and NGINX as a reverse proxy.&lt;/p&gt;

&lt;p&gt;To install PHP 8.2 on Ubuntu we need to add some repositories since it is not available as a default. A good way to add a repository is to use a tool called &lt;code&gt;add-apt-repository&lt;/code&gt;, but again it is not available as a default. The &lt;code&gt;add-apt-repository&lt;/code&gt; tool is available in a package called &lt;code&gt;software-properties-common&lt;/code&gt;. To install this package we can tell Docker to tell Ubuntu to install it (that seems bizarre LOL):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; software-properties-common
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;The flag &lt;code&gt;-y&lt;/code&gt; is there to confirm all prompts by default since &lt;code&gt;apt install&lt;/code&gt; asks for a confirmation midway through.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After the installation is done we can use &lt;code&gt;add-apt-repository&lt;/code&gt; to add the required repository to install &lt;code&gt;php8.2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;add-apt-repository &lt;span class="nt"&gt;-y&lt;/span&gt; ppa:ondrej/php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then update the list of packages again to ensure everything will be installed from the newly added repositories:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Along with PHP itself, we will install Laravel's requirements too:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; php8.2&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-cli&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-common&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-fpm&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-mysql&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-zip&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-gd&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-mbstring&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-curl&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-xml&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-bcmath&lt;span class="se"&gt;\
&lt;/span&gt;    php8.2-pdo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;If you wonder what are all those back-slashes (), they are there to tell docker that the new line character should be escaped.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  PHP FPM &amp;amp; CLI
&lt;/h2&gt;

&lt;p&gt;So far everything is fine for a Laravel application to run, but we want to give it some more speed and we are going to use PHP FPM. (More info about PHP FPM &lt;a href="https://www.php.net/manual/en/install.fpm.php" rel="noopener noreferrer"&gt;here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Here we will install FPM:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; php8.2-fpm php8.2-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;PHP CLI also needs to be installed as it is essential to run many commands especially &lt;code&gt;php artisan&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Composer
&lt;/h2&gt;

&lt;p&gt;As you might know, Composer is a package manager for PHP projects and Laravel uses it too. To install Composer we need to download the installer file and run it with PHP. To download something we can use &lt;code&gt;wget&lt;/code&gt; or &lt;code&gt;curl&lt;/code&gt;. Here we will use curl to download and pipe the result to PHP for installation.&lt;/p&gt;

&lt;p&gt;First, install curl:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, download the file and pip it to PHP:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--install-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin &lt;span class="nt"&gt;--filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;composer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

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

&lt;p&gt;If you are using Laravel as a full-stack framework (both front-end and back-end), you need Node.js too.&lt;/p&gt;

&lt;p&gt;Node's official documentation suggests installing Node on Debian/Ubuntu-based distros (on which our image is based) through Node binary distributions. (&lt;a href="https://github.com/nodesource/distributions?tab=readme-ov-file#ubuntu-versions" rel="noopener noreferrer"&gt;Documentation for Debian/Ubuntu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am not going to dive into full details of the commands since full description is available in the documentation provided above. So once again we will tell Docker to tell ubuntu to run the commands, thus the codes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ca-certificates gnupg
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/apt/keyrings
&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/nodesource.gpg
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NODE_MAJOR 20&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_&lt;/span&gt;&lt;span class="nv"&gt;$NODE_MAJOR&lt;/span&gt;&lt;span class="s2"&gt;.x nodistro main"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/nodesource.list
&lt;span class="k"&gt;RUN &lt;/span&gt;apt update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  NGINX
&lt;/h2&gt;

&lt;p&gt;We will install and configure as a reverse proxy.&lt;/p&gt;

&lt;p&gt;To install NGINX:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once NGINX is installed, we need to add our website configuration. The default website's configuration is located at &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt; so we echo our configuration inside this file and overwrite it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    server {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        listen 80;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        listen [::]:80;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        root /var/www/html/public;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        add_header X-Frame-Options &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;SAMEORIGIN&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        add_header X-Content-Type-Options &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;nosniff&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        index index.php;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        charset utf-8;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location / {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            try_files &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;uri/ /index.php?&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;query_string;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location = /favicon.ico { access_log off; log_not_found off; }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location = /robots.txt  { access_log off; log_not_found off; }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        error_page 404 /index.php;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location ~ &lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;php&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="s2"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_pass unix:/run/php/php8.2-fpm.sock;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            fastcgi_param SCRIPT_FILENAME &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;realpath_root&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;fastcgi_script_name;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            include fastcgi_params;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        location ~ /&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;(?!well-known).* {&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;            deny all;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nginx/sites-available/default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the same configuration suggested by Laravel's official documentation with minor tweaks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We don't need server_name since this container is used server only Laravel and should respond to everything.&lt;/li&gt;
&lt;li&gt;Changed the root to &lt;code&gt;/var/www/html/public&lt;/code&gt; as it is the root of where our application is going to be deployed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fastcgi_pass&lt;/code&gt;'s fpm socket is changed to &lt;code&gt;unix:/run/php/php8.2-fpm.sock&lt;/code&gt; as php8.2-fpm's socket in our scenario is placed here.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Custom shell script to run our application
&lt;/h2&gt;

&lt;p&gt;At this step, we will create a custom shell script to prepare the system and run the app each time the container is started.&lt;/p&gt;

&lt;p&gt;Here is how our bash script looks:&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="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Starting services..."&lt;/span&gt;
service php8.2-fpm start
nginx &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="s2"&gt;"daemon off;"&lt;/span&gt; &amp;amp;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ready."&lt;/span&gt;
&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; 1 /var/log/nginx/&lt;span class="k"&gt;*&lt;/span&gt;.log &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This script starts the FPM service then runs the entry point of nginx and sends it to the background and finally starts printing nginx logs.&lt;/p&gt;

&lt;p&gt;To create this file we can echo it inside a file like below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;&lt;span class="s2"&gt;    #!/bin/sh&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Starting services...&lt;/span&gt;&lt;span class="se"&gt;\"\n\
&lt;/span&gt;&lt;span class="s2"&gt;    service php8.2-fpm start&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    nginx -g &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;daemon off;&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Ready.&lt;/span&gt;&lt;span class="se"&gt;\"\n\
&lt;/span&gt;&lt;span class="s2"&gt;    tail -s 1 /var/log/nginx/*.log -f&lt;/span&gt;&lt;span class="se"&gt;\n\
&lt;/span&gt;&lt;span class="s2"&gt;    "&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I've named the file &lt;code&gt;start.sh&lt;/code&gt; and placed it at the root of the container. You are free to name it anything and place it anywhere you want.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploying Laravel
&lt;/h2&gt;

&lt;p&gt;Now that our environment is ready let's move to deploying Laravel.&lt;/p&gt;

&lt;p&gt;First, copy the current files to &lt;code&gt;/var/www/html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /var/www/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then change the working directory of Docker to the same address:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /var/www/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since Laravel needs access to this folder as well we set the permission of the directory:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; www-data:www-data /var/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And finally, ask Composer to install the ph packages required by Laravel:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;composer &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note: don't run &lt;code&gt;composer install&lt;/code&gt; before setting the permissions. Setting permission of every folder is done recursively and it's better run before all those packages installed since it will take way longer in that case.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Expose port 80
&lt;/h2&gt;

&lt;p&gt;NGINX will try to listen to post 80 and needs to be exposed in order to be bound:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Run the server
&lt;/h2&gt;

&lt;p&gt;Remember the shell script we've created? It is time to run the script when the container is started:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["sh", "/start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And over!&lt;/p&gt;
&lt;h2&gt;
  
  
  Build and run
&lt;/h2&gt;

&lt;p&gt;To build and runt he image use the commands below where a docker instance is available:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t MY_IMAGE .
docker run -p "8000:80" MY_IMAGE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replace &lt;code&gt;MY_IMAGE&lt;/code&gt; with the desired name for your Docker image.&lt;/p&gt;



&lt;p&gt;I hope this article was helpful. Please let me know of any mistakes or improvements.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>docker</category>
      <category>nginx</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Vue 3 Best Practices, Write a Better Code</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Wed, 15 Nov 2023 18:05:45 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/vue-3-best-practices-write-a-better-code-2abc</link>
      <guid>https://dev.to/adnanbabakan/vue-3-best-practices-write-a-better-code-2abc</guid>
      <description>&lt;p&gt;Hey DEV.to community.&lt;/p&gt;

&lt;p&gt;In this article, I will discuss how you should (or at least I believe so :)) organize your Vue 3 code. Although the main focus of this post is based on Vue 3, the principles mentioned here are applicable to Vue 2 and any other framework/library. Please correct me if I'm wrong or you know a better way.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data initialization
&lt;/h1&gt;

&lt;p&gt;You will get your hands dirty with states and data no matter the project. This topic gets harder to manage in certain cases especially when dealing with data being fetched from an external source such as a RESTFul API.&lt;/p&gt;

&lt;p&gt;When initializing a &lt;code&gt;ref&lt;/code&gt; you may pass its default value as you know. However, choosing the correct initial value might be difficult.&lt;/p&gt;

&lt;p&gt;Imagine we want to store an array of products inside a ref. But the array will be fetched from the API and obviously, it needs some time or might fail.&lt;/p&gt;

&lt;p&gt;What you might suggest is to set the default value of &lt;code&gt;products&lt;/code&gt; as &lt;code&gt;ref([])&lt;/code&gt; which generates a ref with an empty array as its default value. The problem with this type of initialization is that you wouldn't know if the actual response of the API was an empty array (for instance no products found) or simply the request failed or something else happened. And for sure you need to have a loading ref to indicate the loading process and use it in your UI to show some loading animation or something.&lt;/p&gt;

&lt;p&gt;So I suggest initializing the value of your &lt;code&gt;products&lt;/code&gt; with &lt;code&gt;ref(null)&lt;/code&gt;. If you do so you may show if the request is loading or the request is finished and there are no results. This mode solves the collision of products being empty and requests failing while the initial value of an empty array is preserved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;'!loading'&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;v-if=&lt;/span&gt;&lt;span class="s"&gt;'products'&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;v-if=&lt;/span&gt;&lt;span class="s"&gt;'products.length &amp;gt; 0'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- Products here --&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;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="c"&gt;&amp;lt;!-- No products found error here --&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;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- Something is actually wrong --&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;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Loading animation here --&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;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&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;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Using lifecycle hooks
&lt;/h1&gt;

&lt;p&gt;Lifecycle hooks are the basic fundamental of any Vue app and give you the power to control what happens in certain steps of the app. The thing most developers tend to do is to write their logic inside the hooks itself which can bring many problems and can toughen debugging or reduce the reusability of the logic.&lt;/p&gt;

&lt;p&gt;Imagine that you want to fetch some data from an API, make some modifications to the result and assign the result to a ref of your choosing. Just like the example above in which we fetched the products and assigned them to the &lt;code&gt;products&lt;/code&gt; ref when the component was mounted.&lt;/p&gt;

&lt;p&gt;The first way you might think of doing so would highly likely look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;This code is absolutely correct and works perfectly. But given that you need to add a refresh button to your app and make your users able to refetch the data you will need to repeat the code inside the &lt;code&gt;onMounted&lt;/code&gt; hook and your code would look like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ....
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"refreshData"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Refresh&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    ....
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refreshData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;Such code is not easy to maintain since if you wanted to make a small change to the procedure of fetching and assigning the data you will need to do it more than once (twice in this case).&lt;/p&gt;

&lt;p&gt;A better solution is to wrap your fetch/assign logic inside another function and call it wherever you need:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ....
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"getProductsHandler"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Refresh&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    ....
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&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;getProductsHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProductsHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;Now you only have one base for your logic and it is way simpler, cleaner and easier to make changes to.&lt;/p&gt;
&lt;h1&gt;
  
  
  Computed values and side effects
&lt;/h1&gt;

&lt;p&gt;Well, this one is super important and can save you a lot of time when you don't know what is happening inside your app and you are losing your mind over it.&lt;/p&gt;

&lt;p&gt;Some JavaScript methods/functions have side effects, meaning that they mutate (a fancy word for changing :)) the original value as well. For instance, &lt;code&gt;reverse()&lt;/code&gt; method of arrays in JS not only returns the reverse of an array, but it actually reverses the original array as well.&lt;/p&gt;

&lt;p&gt;To test this scenario you can run the code below in any JS environment:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// [5, 4, 3, 2, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now imagine you reach the same approach inside of a computed value in Vue:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reverseOfArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;This kind of method can ruin your app and result in unexpected behaviours.&lt;/p&gt;

&lt;p&gt;As seen in the JS code, although this computed value returns the reverse of the array, it mutates the original value as well, so each time the value of &lt;code&gt;arr&lt;/code&gt; is changed the computed value is going to be recalculated thus changing your original value as well.&lt;/p&gt;

&lt;p&gt;Avoid using such methods inside computed values. Instead of the computed value above you better write it yourself in an imperative way to make sure the behaviour you get is the one you want:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&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;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reverseOfArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&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="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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="nx"&gt;t&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Mutating props
&lt;/h1&gt;

&lt;p&gt;It is always suggested against mutating the props directly. Props are the values you receive from the parent component (the component where the current component is called from).&lt;/p&gt;

&lt;p&gt;Imagine we want to have a simple number input component with two simple increase and decrease buttons. Here is how to implement it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&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;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;'decrease'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;-&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;'increase'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;+&lt;span class="nt"&gt;&amp;lt;/button&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;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineEmits&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;udpate:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;increase&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decrease&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;emits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;udpate:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&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;As you can see, it is better to assign the value of &lt;code&gt;modelValue&lt;/code&gt; (which is a special prop that is attached to &lt;code&gt;v-model&lt;/code&gt; when the component is used) to a secondary ref and manipulate its data instead of &lt;code&gt;props.modelValue&lt;/code&gt;. Then by watching the value of &lt;code&gt;v&lt;/code&gt; we may use an emit called &lt;code&gt;update:modelValue&lt;/code&gt; to inform the parent component about the recent changes to the value.&lt;/p&gt;



&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;Feel free to contact me if you have any questions or suggestions.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Implement UUID primary key in Laravel, and its benefits</title>
      <dc:creator>Adnan Babakan (he/him)</dc:creator>
      <pubDate>Thu, 13 Jul 2023 00:26:52 +0000</pubDate>
      <link>https://dev.to/adnanbabakan/implement-uuid-primary-key-in-laravel-and-its-benefits-55o3</link>
      <guid>https://dev.to/adnanbabakan/implement-uuid-primary-key-in-laravel-and-its-benefits-55o3</guid>
      <description>&lt;p&gt;Hey, DEV.to community!&lt;/p&gt;

&lt;p&gt;It's been a long time since I last wrote here.&lt;/p&gt;

&lt;p&gt;During the time that I've been absent, I've been working on some large-scale projects in which I've seen how UUIDs can benefit your application in multiple ways.&lt;/p&gt;

&lt;p&gt;I've been using UUIDs as my primary key structure for a fair amount of time now but the real advantages have shown themselves after finishing the projects and I am glad I've decided to do so.&lt;/p&gt;

&lt;p&gt;I primarily use Laravel as my back-end and love using MySQL (I know there are lots of other RDBMS/DBMS out there but I love MySQL and feel comfortable with it XD). Although when using MySQL or many other databases your primary key is set as an AI (auto-incremental) and the data type is an integer, you may use UUID with a few tweaks and believe me it's worth the hassle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuv56iksr0zeq2qylkyv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbuv56iksr0zeq2qylkyv.gif" alt="Angry type" width="450" height="337"&gt;&lt;/a&gt;&lt;/p&gt;
Me when coding.



&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Enumeration exploit fix
&lt;/h3&gt;

&lt;p&gt;An enumeration exploit is when your data is predictable. Let's say for instance you upload a video on YouTube which is hidden from the public and can only be viewed by those whom you shared the link with. Well, Let's look at a YouTube link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.youtube.com/watch?v=3wVTmlD86a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
My favorite song BTW




&lt;p&gt;As you can see the address ends in &lt;code&gt;v=3wVTmlD86a&lt;/code&gt; which indicates the (let's say) ID of the video. So imagine YouTube used a numerical index and incremented it one by one for each video uploaded. Then what you might ask. In that case, someone could start from number 1 and try every link using a custom-made program to extract all the available videos on YouTube and your link-only video would be exposed as well.&lt;/p&gt;

&lt;p&gt;This is called enumeration exploiting which can cause serious data leaks depending on what your program is supposed to do.&lt;/p&gt;

&lt;p&gt;The algorithm YouTube uses to make IDs for their videos is custom, but the purpose of my description is the same for UUIDs.&lt;/p&gt;

&lt;p&gt;Given a UUID such as &lt;code&gt;700234f5-0e45-452e-ae3a-70b4b3d024e1&lt;/code&gt;, you wouldn't know what UUID is before or after this since there is no order. As you can see this can solve the enumeration exploit in your application.&lt;/p&gt;
&lt;h3&gt;
  
  
  Horizontally expandable databases
&lt;/h3&gt;

&lt;p&gt;Let's imagine that you have two database instances of the same system that you want to expand or just make a new cluster for some reason and then merge both instances. Given that the database structure is the same and you have complex relations in your database, you might find it difficult to merge data without manually adjusting some values or using an automated task.&lt;/p&gt;

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

&lt;p&gt;As you can see in the simple diagram above of an abstract database, you might have a table of orders, which is related to both a product and a user.&lt;/p&gt;

&lt;p&gt;Now let's think about this: In each of your database instances, you only have 10 users and 10 products, and 10 orders which are numerically indexed from 1 to 10. Let's say in our first database instance, order 2 is related to user ,3 whose name is &lt;code&gt;Adnan Babakan&lt;/code&gt;. In the other instance, order 2 is related to use 3 as well but their name is &lt;code&gt;Arian Amini&lt;/code&gt;. Even if we import the orders properly and their IDs aren't referenced from other tables and their indexes are reassigned from 1 to 20, since the users are reindexed as well now our orders reference wrong users!&lt;/p&gt;

&lt;p&gt;I suppose you see the problem and solution now. If we use UUIDs, since they are globally unique there will be no collision between our data and we can merge as many instances as we want with no problem.&lt;/p&gt;

&lt;p&gt;Apart from merging two databases, UUIDs make it easier to manage a cluster-based database architecture as well with multiple database instances running at the same time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Downsides
&lt;/h2&gt;

&lt;p&gt;There are two main downsides to using UUIDs in databases. First is the size it takes in your database and second is the insert problem.&lt;/p&gt;

&lt;p&gt;Since UUIDs aren't ordered performing an insert operation becomes costly because your record will be inserted somewhere random rather than at the end of your table when using a numerical index system.&lt;/p&gt;

&lt;p&gt;Even though these disadvantages are present, it is forgivable as space isn't that expensive and the insert problem isn't such a big deal for most cases.&lt;/p&gt;

&lt;p&gt;There is a way to avoid the insert problem which is using the same numerical index system as before but assigning a separate UUID for each record as well so you benefit from the points aforementioned.&lt;/p&gt;


&lt;h2&gt;
  
  
  Using UUIDs in Laravel
&lt;/h2&gt;

&lt;p&gt;In this section of the article, I will discuss how you can implement UUIDs in your Laravel application and the problems I faced and how I solved them. Remember that UUIDs are NOT for Laravel/MySQL only and you may use them in any other programming language, framework and database you like.&lt;/p&gt;

&lt;p&gt;Keep in mind this is my preferred way of implementing such an approach and you might find a more efficient way, and let me know in the comments if you did so.&lt;/p&gt;
&lt;h3&gt;
  
  
  Migrations
&lt;/h3&gt;

&lt;p&gt;The first thing you need to do is know how to define your migrations so your tables use UUID.&lt;/p&gt;

&lt;p&gt;Fortunately, Laravel comes packed with many good methods and stuff to help you with your goal.&lt;/p&gt;

&lt;p&gt;First of all, let's change how we define our PK (primary key) in a migration. This is how you usually define your PK in a Laravel migration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code above is equivalent of:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;integer&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Unfortunately, there is no shorthand method for creating a UUID-based PK in migrations. But it isn't that much of a work either:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;uuid&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;TADA! Now your table will have a column named &lt;code&gt;id&lt;/code&gt; which holds UUIDs.&lt;/p&gt;
&lt;h4&gt;
  
  
  References and relations
&lt;/h4&gt;

&lt;p&gt;Now let's talk about relations. A relation is when you want to reference a different record from another table or the same table. Referencing is done using the target record's id since it is the unique key that you are sure will never be duplicated.&lt;/p&gt;

&lt;p&gt;Imagine you want to reference a user in your table, this is how you define a normal relation in your migrations:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;constrained&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Keep in mind the &lt;code&gt;constrained()&lt;/code&gt; method is a shorthand for:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;references&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Laravel gives you the power of the shorthand at the cost of following naming conventions. So when your foreign id column is named &lt;code&gt;user_id&lt;/code&gt; and &lt;code&gt;constrained()&lt;/code&gt; is called afterwards, Laravel knows you mean that this &lt;code&gt;user_id&lt;/code&gt; will reference the &lt;code&gt;id&lt;/code&gt; column on the &lt;code&gt;users&lt;/code&gt; table. If it is not the case you must define it using the &lt;code&gt;references()&lt;/code&gt; and the &lt;code&gt;on()&lt;/code&gt; methods to specifically determine what you mean.&lt;/p&gt;

&lt;p&gt;To reference a foreign id which is a UUID, you may use the &lt;code&gt;foreignUuid()&lt;/code&gt; method instead of &lt;code&gt;foreignId()&lt;/code&gt; method. The rest is the same and you can apply &lt;code&gt;constrained()&lt;/code&gt; to a foreign UUID reference as well. This is how you reference a user record given that the &lt;code&gt;users&lt;/code&gt; table utilizes UUID as its PK structure.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignUuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;constrained&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or more elaborately:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignUuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;references&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Models
&lt;/h3&gt;

&lt;p&gt;Now that you've successfully defined your migrations, there is a small tweak you need to make on your models.&lt;/p&gt;

&lt;p&gt;A model's defaults tell it to utilize integer-based ids and we should tell the model that it is not the case.&lt;/p&gt;

&lt;p&gt;First, add a private property named &lt;code&gt;$keyType&lt;/code&gt; to your model and set its value as &lt;code&gt;'string'&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$keyType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This tells the model that your key is a type of string and not an integer (UUIDs are strings).&lt;/p&gt;

&lt;p&gt;The second thing to do is tell the model not to use the incrementing system for this type of key which is done by setting the &lt;code&gt;$incrementing&lt;/code&gt; property as &lt;code&gt;false&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$incrementing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After doing these your model know how your PK works perfectly.&lt;/p&gt;

&lt;p&gt;But wait! Is there a problem you face when creating a new record telling you that &lt;code&gt;id&lt;/code&gt; cannot be null and doesn't have a default value?&lt;/p&gt;

&lt;p&gt;To solve this issue either you have to define a UUID each time you create a new record such as 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="nv"&gt;$new_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$new_user&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="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;uuid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$new_user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Adnan'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$new_user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'helloWorld'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$new_user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;The &lt;code&gt;Str&lt;/code&gt; class is imported from &lt;code&gt;Illuminate\Support\Str&lt;/code&gt;. The &lt;code&gt;Str::uuid()&lt;/code&gt; helper creates a new UUID for you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Or you can use model events to tell Laravel how to create an ID for your model when creating the record on the database.&lt;/p&gt;

&lt;p&gt;This can be done simply by using closure events in your &lt;code&gt;booted&lt;/code&gt; method. Add a static method called &lt;code&gt;booted&lt;/code&gt; to your model:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;booted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then you can use an event called &lt;code&gt;creating&lt;/code&gt; inside of it and tell it to make a UUID and assign it to your model's id:&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;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;booted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;creating&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="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$model&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="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;uuid&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;You can read more about model events at &lt;a href="https://laravel.com/docs/10.x/eloquent#events-using-closures" rel="noopener noreferrer"&gt;https://laravel.com/docs/10.x/eloquent#events-using-closures&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are using the old &lt;code&gt;boot&lt;/code&gt; method, remember to call the parent's &lt;code&gt;boot&lt;/code&gt; method so it is not overwritten:&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;static&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="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;creating&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="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$model&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="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;uuid&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;If you've followed so far, your &lt;code&gt;User&lt;/code&gt; model or any other model should look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="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="mf"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$keyType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'string'&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;$incrementing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="mf"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&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="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;creating&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="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$model&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="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;uuid&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;h3&gt;
  
  
  Solving the Sanctum problem
&lt;/h3&gt;

&lt;p&gt;If you try to use Sanctum to issue your tokens you might realize that you face an error telling you that your constraints fail. This is because your &lt;code&gt;personal_access_tokens&lt;/code&gt; table is designed to reference integer-based foreign ids (this table uses morphs as it should be able to reference multiple types of models).&lt;/p&gt;

&lt;p&gt;In case you already have a project running you should change the &lt;code&gt;tokenable_id&lt;/code&gt; column's type in your &lt;code&gt;personal_access_tokens&lt;/code&gt; table using a new migration.&lt;/p&gt;

&lt;p&gt;First, create a new migration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:migration change_tokenable_id_type_in_personal_access_tokens_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then in your migration use the &lt;code&gt;change()&lt;/code&gt; method on the &lt;code&gt;tokenable_id&lt;/code&gt; column:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignUuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tokentable_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;change&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This changes the data type of &lt;code&gt;tokenable_id&lt;/code&gt; to reference UUIDs instead of integers.&lt;/p&gt;

&lt;p&gt;To make our database structure unified I'd like to make my token records use UUID as their ids as well so add the instruction below as well:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;uuid&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;primary&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;change&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you receive an error running this migration install the &lt;code&gt;doctrine/dbal&lt;/code&gt; package using composer.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require doctrine/dbal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Although the method described above is the proper way to change the data type of the &lt;code&gt;tokenable_id&lt;/code&gt; column, there is a simpler way of doing so if you are just starting a new project or you don't care about your current data and are willing to refresh your migration (which will delete your data).&lt;/p&gt;

&lt;p&gt;Just open the &lt;code&gt;2019_12_14_000001_create_personal_access_tokens_table.php&lt;/code&gt; file (the date at the beginning might differ) and change:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;morphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tokenable'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;uuidMorphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'tokenable'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and change:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;uuid&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="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and then run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&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 plaintext"&gt;&lt;code&gt;php artisan migrate:fresh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;if you've already run your migrations before.&lt;/p&gt;

&lt;p&gt;Now that our &lt;code&gt;personal_access_tokens&lt;/code&gt; can reference UUIDs and its id is also a UUID we need to make Laravel know how to treat our tokens as Sanctum uses a default model to handle these records.&lt;/p&gt;

&lt;p&gt;First, let's create a new model that will be the model Sanctum uses since we've changed the structure:&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;make&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="nc"&gt;PersonalAccessToken&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now open the created model's file and instead of extending the &lt;code&gt;Model&lt;/code&gt; class, extend the class by &lt;code&gt;Laravel\Sanctum\PersonalAccessToken&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Sanctum\PersonalAccessToken&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;SanctumPersonalAccessToken&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;PersonalAccessToken&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SanctumPersonalAccessToken&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;em&gt;Since our class has the same name as the class used by Sanctum's default PersonalAccessToken class, you should either define an alias when importing it or use absolute naming after the &lt;code&gt;extend&lt;/code&gt; keyword like: &lt;code&gt;\Laravel\Sanctum\PersonalAccessToken&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We have to make sure Laravel knows how this model works just as before. So we should set &lt;code&gt;$keyType&lt;/code&gt;, &lt;code&gt;$incrementing&lt;/code&gt; and define an event to create a UUID for the id of each record.&lt;/p&gt;

&lt;p&gt;This is how your final &lt;code&gt;PersonalAccessToken&lt;/code&gt; model should look like:&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="mf"&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\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;Laravel\Sanctum\PersonalAccessToken&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;SanctumPersonalAccessToken&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mf"&gt;...&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PersonalAccessToken&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SanctumPersonalAccessToken&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;public&lt;/span&gt; &lt;span class="nv"&gt;$keyType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'string'&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;$incrementing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="mf"&gt;....&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&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="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;creating&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="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$model&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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;uuid&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="mf"&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 define this model as the model used by Sanctum. This step can be done by using the &lt;code&gt;Sanctum::usePersonalAccessTokenModel()&lt;/code&gt; method. This method should be called in a provider file. I prefer &lt;code&gt;AppServiceProvider&lt;/code&gt; which is located at &lt;code&gt;app/Providers/AppServiceProvider.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open the provider file and add the code below inside of the &lt;code&gt;boot&lt;/code&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;Sanctum&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;usePersonalAccessTokenModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PersonalAccessToken&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;em&gt;Remember to import &lt;code&gt;Sanctum&lt;/code&gt; and your custom &lt;code&gt;PersonalAccessToken&lt;/code&gt; classes properly. The &lt;code&gt;Sanctum&lt;/code&gt; class is imported from &lt;code&gt;Laravel\Sanctum\Sanctum&lt;/code&gt; and your custom &lt;code&gt;PersonalAccessToken&lt;/code&gt; is imported from &lt;code&gt;App\Models\PersonalAccessToken&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And now you are done implementing UUIDs in your Laravel application!&lt;/p&gt;



&lt;p&gt;I hope you enjoyed this article and it helped you do what you wanted to do. Kindly let me know if there are any mistakes in this article or if you know a better way to do something.&lt;/p&gt;

&lt;p&gt;BTW! Check out my free Node.js Essentials E-book here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanbabakan" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F241266%2Fcec6a6bb-2d41-48b8-a16a-dc5af3941a3d.jpg" alt="adnanbabakan"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/adnanbabakan/nodejs-essentials-free-e-book-5319" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;NodeJS Essentials | Free E-Book&lt;/h2&gt;
      &lt;h3&gt;Adnan Babakan (he/him) ・ Sep 11 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#books&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>laravel</category>
      <category>php</category>
      <category>database</category>
      <category>uuid</category>
    </item>
  </channel>
</rss>
