<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Yurich</title>
    <description>The latest articles on Forem by Yurich (@yurich84).</description>
    <link>https://forem.com/yurich84</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%2F1052904%2Fa44c8ee0-0796-46c2-852f-2c23b170dc0e.png</url>
      <title>Forem: Yurich</title>
      <link>https://forem.com/yurich84</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/yurich84"/>
    <language>en</language>
    <item>
      <title>My own Tinkerwell-like Script</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Wed, 05 Mar 2025 23:21:07 +0000</pubDate>
      <link>https://forem.com/yurich84/my-tinkerwell-script-gpg</link>
      <guid>https://forem.com/yurich84/my-tinkerwell-script-gpg</guid>
      <description>&lt;p&gt;I like the idea of Tinkerwell. It looks very convenient when you need to execute a query or command using Laravel syntax.&lt;br&gt;
Especially, I missed this when I needed to run a query on staging or production.&lt;/p&gt;

&lt;p&gt;I do not recommend running any queries on production. In general, no one should have easy access to production. But there are situations where it really helps.&lt;/p&gt;

&lt;p&gt;Usually, you need to log into production via SSH, find the necessary container, and, if needed, switch to the correct node.&lt;/p&gt;

&lt;p&gt;Let's create our own script to handle this task.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the script file
&lt;/h3&gt;

&lt;p&gt;Create a file outside of Git, for example:&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; ./storage/framework/testing/tinko.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the code that you want to execute on production. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;inRandomOrder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run it locally very easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan tinker tinker storage/framework/testing/tinko.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running it on production
&lt;/h3&gt;

&lt;p&gt;To run this on production, create a script in the same folder that will execute this code:&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; ./storage/framework/testing/tinko.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the following content:&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="nv"&gt;SERV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root@name-of-your-server-or-ip.com
&lt;span class="nb"&gt;cat&lt;/span&gt; ./storage/framework/testing/tinko.php | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/&amp;lt;?php//g'&lt;/span&gt; | ssh &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$SERV&lt;/span&gt; &lt;span class="s2"&gt;"php artisan tinker"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What is happening here?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We store the production server path in the &lt;code&gt;SERV&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;The last command takes our PHP script, removes &lt;code&gt;&amp;lt;?php&lt;/code&gt;, and passes it for execution in Tinker via SSH.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't forget to give execution permissions to the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./storage/framework/testing/tinko.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the command and see the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./storage/framework/testing/tinko.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Some issues
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The full content of the file is dumped into the console.&lt;/li&gt;
&lt;li&gt;There is no syntax highlighting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But these are minor issues that can be tolerated.&lt;/p&gt;

&lt;p&gt;You can add an alias for the command to avoid typing the full path or even create a separate Run configuration in your IDE.&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%2Fww7zmc3l63du91hfwznq.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%2Fww7zmc3l63du91hfwznq.png" alt="Image description" width="512" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Running a new Docker container for the script
&lt;/h3&gt;

&lt;p&gt;Sometimes, you may need to start a new Docker container to execute the script. In that case, do the following:&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="nv"&gt;SERV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root@name-of-your-server.com
&lt;span class="nv"&gt;COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"docker run -i --rm image_name php artisan tinker"&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ./storage/framework/testing/tinko.php | &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/&amp;lt;?php//g'&lt;/span&gt; | ssh &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$SERV&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COMMAND&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finding a container ID before execution
&lt;/h3&gt;

&lt;p&gt;If you need to find the container ID before executing the script, you can use the following script:&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="nv"&gt;STAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root@name-of-your-server.com

&lt;span class="nv"&gt;CONTAINER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ssh &lt;span class="nv"&gt;$STAGE&lt;/span&gt; &lt;span class="s2"&gt;"docker ps --format '{{.ID}}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;{{.Image}}'"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'app.'&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;cat&lt;/span&gt; ./storage/framework/testing/tinko.php | &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/&amp;lt;?php//g'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
ssh &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$STAGE&lt;/span&gt; &lt;span class="s2"&gt;"docker exec -i &lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_ID&lt;/span&gt;&lt;span class="s2"&gt; php artisan tinker"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Use with caution.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>programming</category>
      <category>php</category>
      <category>devops</category>
    </item>
    <item>
      <title>Crafting a Modular Laravel API for Effective SPA Interaction</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Sun, 17 Mar 2024 11:19:17 +0000</pubDate>
      <link>https://forem.com/yurich84/crafting-a-modular-laravel-api-for-effective-spa-interaction-2pc8</link>
      <guid>https://forem.com/yurich84/crafting-a-modular-laravel-api-for-effective-spa-interaction-2pc8</guid>
      <description>&lt;h4&gt;
  
  
  Let's create Laravel app
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;composer create-project laravel/laravel example-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or &lt;code&gt;laravel new example-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;go to app folder &lt;code&gt;cd example-app&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now you can run &lt;code&gt;php artisan serve&lt;/code&gt; and visit &lt;a href="http://127.0.0.1:8000/"&gt;http://127.0.0.1:8000&lt;/a&gt; to verify that the website is working.&lt;/p&gt;

&lt;p&gt;Remember that we need to adjust the &lt;code&gt;.env&lt;/code&gt; file, specifically to configure the database connection and specify the correct URL &lt;code&gt;APP_URL=http://127.0.0.1:8000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we don't have API routes it can be easily fixed by running the command &lt;code&gt;php artisan install:api&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's proceed to create a modular structure. The modules will be located in the &lt;code&gt;Modules&lt;/code&gt; folder, so let's create them in the &lt;code&gt;app&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;First of all, let's dynamically include all routes. To do this, go to &lt;code&gt;app.php&lt;/code&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Route&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'API_PREFIX'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'API_PREFIX'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'api/v1'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="nv"&gt;$modules_folder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Modules'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="nv"&gt;$modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
    &lt;span class="nb"&gt;array_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;  
        &lt;span class="nb"&gt;scandir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$modules_folder&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;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$modules_folder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;is_dir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$modules_folder&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;in_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'..'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$modules&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nv"&gt;$routesPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$modules_folder&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="no"&gt;DIRECTORY_SEPARATOR&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'routes_api.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$routesPath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;API_PREFIX&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;namespace&lt;/span&gt;&lt;span class="p"&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;App&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Modules&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="s2"&gt;\Controllers"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$routesPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make the SPA works, you need to add one more route at the end of the &lt;code&gt;web.php&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/{any}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'spa'&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'any'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'^(?!api).*'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need to create a Blade template &lt;code&gt;spa.blade.php&lt;/code&gt; for the main route where Vue will be connected with libraries.&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;!DOCTYPE html&amp;gt;&lt;/span&gt;  
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"{{ str_replace('_', '-', app()-&amp;gt;getLocale()) }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;        
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"csrf-token"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"{{ csrf_token() }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;  
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;{{ config('app.name') }}&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all routes that do not start with &lt;code&gt;/api&lt;/code&gt; will be directed to this template. This will enable front-end routing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a Restful API
&lt;/h3&gt;

&lt;p&gt;Following the modular system laid out in the article &lt;a href="https://dev.to/yurich84/my-point-of-view-on-spa-modularity-using-laravel-and-vue-52g0"&gt;My point of view on SPA modularity using Laravel and Vue.js&lt;/a&gt;, let's create the first module.&lt;/p&gt;

&lt;p&gt;To begin, let's create a folder &lt;code&gt;app\Modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's assume our CRM will have a system for managing static pages, meaning we need CRUD functionality for this.&lt;/p&gt;

&lt;h5&gt;
  
  
  Execute the command to create a model and migration
&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;php artisan make:model Page -m&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Edit the created files
&lt;/h5&gt;

&lt;p&gt;Add the &lt;code&gt;name&lt;/code&gt; field to both the migration file and the model. The code for the files will look accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migration&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="cd"&gt;/**  
     * Run the migrations.     *     * @return void  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
        &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Reverse the migrations.     
     *     
     * @return void  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pages'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Model&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Factories\HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Page&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;HasFactory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;COLUMN_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;COLUMN_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$guarded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;COLUMN_ID&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 run the migrations: &lt;code&gt;php artisan migrate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Modules&lt;/code&gt; directory, create a folder named &lt;code&gt;Page&lt;/code&gt;, which will contain the following files:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;routes_api.php&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

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

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;apiResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pages'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'PageController'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Controllers/PageController.php&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Modules\Page\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Modules\Page\Requests\PageRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Modules\Page\Resources\PageResource&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;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Builder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\JsonResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Resources\Json\AnonymousResourceCollection&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;PageController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="cd"&gt;/**  
     * Display list of resources     
     *     
     * @param  Request  $request  
     * @return AnonymousResourceCollection  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sortBy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id,asc'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
        &lt;span class="nv"&gt;$pageSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pageSize'&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="nv"&gt;$resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;query&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;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;filled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'search'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Builder&lt;/span&gt; &lt;span class="nv"&gt;$q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
                &lt;span class="nv"&gt;$q&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;COLUMN_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'like'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&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="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$pageSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;PageResource&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$resource&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Store a newly created resource in storage.     
     *
     * @param  PageRequest  $request  
     * @param  Page  $page  
     * @return JsonResponse  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PageRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Page&lt;/span&gt; &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
        &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&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;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;  
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RESPONSE_TYPE_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
            &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Successfully created'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;]);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Display the specified resource.     
     *
     * @param  Page  $page  
     * @return PageResource  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Page&lt;/span&gt; &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PageResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Update the specified resource in storage.     
     *
     * @param  PageRequest  $request  
     * @param  Page  $page  
     * @return JsonResponse  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;PageRequest&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Page&lt;/span&gt; &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
        &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&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;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;  
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RESPONSE_TYPE_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
            &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Successfully updated'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;]);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  

    &lt;span class="cd"&gt;/**  
     * Delete the specified resource.     
     *     
     * @param  Page  $page  
     * @return JsonResponse  
     *  
     * @throws Exception  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Page&lt;/span&gt; &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;  
            &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RESPONSE_TYPE_SUCCESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
            &lt;span class="s1"&gt;'message'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Successfully deleted'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;]);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It would be convenient to add constants in &lt;code&gt;App\Http\Controllers\Controller&lt;/code&gt; so they can be used for response status.&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;const&lt;/span&gt; &lt;span class="no"&gt;RESPONSE_TYPE_SUCCESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;RESPONSE_TYPE_INFO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'info'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;RESPONSE_TYPE_WARNING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'warning'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;RESPONSE_TYPE_ERROR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'error'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Requests/PageRequest.php&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Modules\Page\Requests&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Page&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Http\FormRequest&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;PageRequest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;FormRequest&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="cd"&gt;/**  
     * Determine if the user is authorized to make this request.     
     *     
     * @return bool  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;authorize&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="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="cd"&gt;/**  
     * Get the validation rules that apply to the request.     
     *     
     * @return array  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;  
            &lt;span class="nc"&gt;Page&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;COLUMN_NAME&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'required|string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="p"&gt;];&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Resources/PageResource.php&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Modules\Page\Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Resources\Json\JsonResource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PageResource&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JsonResource&lt;/span&gt;  
&lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="cd"&gt;/**  
     * Transform the resource into an array.     
     *     
     * @param  Request  $request  
     * @return array  
     */&lt;/span&gt;  
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Currently, this class doesn't provide much assistance, but it will set a standard response and unload the controller in the future.&lt;/p&gt;

&lt;p&gt;Our Restful API for managing the Page entity is ready.&lt;br&gt;
The list of routes for this module you can find running this command &lt;/p&gt;

&lt;p&gt;&lt;code&gt;php artisan route:list --path=pages&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you comment out the line &lt;code&gt;-&amp;gt;middleware(['auth:sanctum'])&lt;/code&gt; in the &lt;code&gt;api.php&lt;/code&gt; file, you can easily test this functionality using Postman.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>api</category>
      <category>backend</category>
      <category>php</category>
    </item>
    <item>
      <title>Groundwork SPA with a full-fledged CRUD generator</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Mon, 19 Feb 2024 00:00:00 +0000</pubDate>
      <link>https://forem.com/yurich84/groundwork-spa-with-a-full-fledged-crud-generator-l2a</link>
      <guid>https://forem.com/yurich84/groundwork-spa-with-a-full-fledged-crud-generator-l2a</guid>
      <description>&lt;p&gt;In the previous article, I described the SPA modules and provided you with a foundation for developing such an application. Now let's dive deeper into this project and its capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Yurich84/laravel-vue3-spa"&gt;https://github.com/Yurich84/laravel-vue3-spa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the project, I chose Laravel and Vue3 with Composition API. Since the application is planned to be large, we will need a state manager system like Pinia. For authentication, we'll use &lt;a href="https://websanova.com/docs/vue-auth/home"&gt;Vue-Auth&lt;/a&gt;, &lt;a href="https://github.com/mzabriskie/axios"&gt;Axios&lt;/a&gt;, and &lt;a href="https://laravel.com/docs/8.x/sanctum"&gt;Sanctum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For rapid development, the ElementPlus UI Kit was used. Also, there are libraries without which no large project can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://lodash.com/"&gt;Lodash&lt;/a&gt; js utilities&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dayjs.com/"&gt;Day.js&lt;/a&gt; time manipulations&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://fontawesome.io/icons/"&gt;FontAwesome 6&lt;/a&gt; icons&lt;/li&gt;
&lt;li&gt;&lt;a href="https://router.vuejs.org/"&gt;VueRouter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kazupon.github.io/vue-i18n/"&gt;VueI18n&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the modules are entirely independent, I created a set of templates for each module file and a command that allows generating a fully functional CRUD ready to use.&lt;/p&gt;

&lt;p&gt;By executing the command &lt;code&gt;php artisan make:module {ModuleName}&lt;/code&gt;, all necessary files will appear, including the model and migrations for a fully functional CRUD operation. You just need to execute migrations &lt;code&gt;php artisan migrate&lt;/code&gt;, and everything will work. Along with this, a file with functional tests is generated to cover this CRUD. Most likely, you will need to add additional fields, so before migrating, don't forget to add them to the model, migration, and also display them in vue.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0qKNlrmhgNg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The first version of the application used older technologies but was no less useful. Here it is: &lt;a href="https://github.com/Yurich84/laravel-vue-spa-skeleton"&gt;https://github.com/Yurich84/laravel-vue-spa-skeleton&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the new project, I decided to change several libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replaced Vuex with Pinia&lt;/li&gt;
&lt;li&gt;Moved to Vue3 Composition API&lt;/li&gt;
&lt;li&gt;Replaced moment.js with the lighter day.js&lt;/li&gt;
&lt;li&gt;Used Vite instead of webpack for the builder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Initially, this groundwork was developed for my needs, but now I hope it will be useful for other users.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>vue</category>
      <category>php</category>
    </item>
    <item>
      <title>My point of view on SPA modularity using Laravel and Vue</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Mon, 12 Feb 2024 15:43:28 +0000</pubDate>
      <link>https://forem.com/yurich84/my-point-of-view-on-spa-modularity-using-laravel-and-vue-52g0</link>
      <guid>https://forem.com/yurich84/my-point-of-view-on-spa-modularity-using-laravel-and-vue-52g0</guid>
      <description>&lt;p&gt;Working on various SPA projects, I noticed that I often have to do the same actions repeatedly. We repeatedly connect the same libraries, make familiar configurations, establish the known application structure, and create similar modules. I decided to optimize this process and created a foundation for a large SPA using Laravel and Vue3.&lt;/p&gt;

&lt;p&gt;In this article, I will share my perspective on the SPA structure using Laravel and Vue.js. We will design and establish the application architecture to make it flexible and scalable from the outset. Later, we will select the appropriate libraries to use throughout the development process. We will create CRUD and lay down modularity suitable for developing various CRMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  I want this application to meet the following criteria:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reduce project maintenance time and code navigation&lt;/li&gt;
&lt;li&gt;Reduce the start project time&lt;/li&gt;
&lt;li&gt;Avoid high cohesion between modules&lt;/li&gt;
&lt;li&gt;Be understandable for programmers with little experience&lt;/li&gt;
&lt;li&gt;Help avoid code duplication&lt;/li&gt;
&lt;li&gt;Be easily extensible&lt;/li&gt;
&lt;li&gt;Lay the groundwork for writing high-quality code in the future&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make life easier and not get lost in the project, it is necessary to structure it correctly. Initially, the application should be divided into responsibility levels, such as user interface, database, and business logic.&lt;/p&gt;

&lt;p&gt;Next, each layer should be divided first by functionality - these will be separate modules. And then the code of each module should be divided into files according to the chosen pattern.&lt;/p&gt;

&lt;p&gt;Inspired by the DDD philosophy, I decided to divide both the front-end and back-end into semantic modules. But these are not classical domains described by Evans. His model is also not ideal. In any application, there are always relationships between components — relationships between models.&lt;/p&gt;

&lt;p&gt;Backend models will remain a separate layer because they duplicate the database with all its relationships.&lt;/p&gt;

&lt;p&gt;Let's move into the module the files we always create when developing new functionality. These are routes, controllers, request classes, and resource classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ModuleName}/
│  
|── routes_api.php  
│  
|── Controllers/
|   |
│   └── {ModuleName}Controller.php  
│  
|── Requests/
|   |
│   └── {ModuleName}Request.php
|
|── Resources/
    |
    └── {ModuleName}Resource.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other design patterns like events, jobs, policies, etc., are used less frequently, and you can decide whether to keep them as a separate layer or include them in modules.&lt;/p&gt;

&lt;p&gt;We will also build the frontend part following this modular logic. The structure of one module will be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{moduleName}/
│
├── routes.js
│
|── {moduleName}Api.js
│
|── {moduleName}Store.js
│
|── components/
    |── {ModuleName}List.vue
    |── {ModuleName}View.vue
    └── {ModuleName}Form.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The module will contain a &lt;code&gt;routes.js&lt;/code&gt; file, &lt;code&gt;{moduleName}Api.js&lt;/code&gt; - a file where all promises and backend calls will be located. &lt;code&gt;{moduleName}Store.js&lt;/code&gt; - a separate file will host the Store, where actions, getters, and other application state variables will be located. And we will need a folder with components. All of this should be connected automatically without unnecessary movements. All manipulations with dynamically loading modules are done to minimize coupling between them. This allows adding and removing modules without consequences.&lt;/p&gt;

&lt;p&gt;I will explain how all of this works in the next articles, and for now, I leave a link to the ready-made groundwork here. This project also has its own module generator, which will create all necessary files for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Yurich84/laravel-vue3-spa"&gt;https://github.com/Yurich84/laravel-vue3-spa&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will describe this project in more detail in my next article.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>vue</category>
      <category>spa</category>
      <category>modular</category>
    </item>
    <item>
      <title>Comparison of barcode scanner libraries</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Tue, 18 Apr 2023 09:38:15 +0000</pubDate>
      <link>https://forem.com/yurich84/comparison-of-barcode-scanner-libraries-4feg</link>
      <guid>https://forem.com/yurich84/comparison-of-barcode-scanner-libraries-4feg</guid>
      <description>&lt;p&gt;I was working on a web application that needed a barcode scanner that would work on all devices and platforms.&lt;/p&gt;

&lt;p&gt;5 powerful libraries were selected. Three paid and two free.&lt;br&gt;
Let's look at their main characteristics and highlight the pros and cons.&lt;br&gt;
To compare how accurately they recognize the barcode, I chose different products with codes of different sizes and scanned them one by one without paying attention to the lighting.&lt;br&gt;
For the experiment, I used two browsers on a 2011 Macbook and two browsers on an Android phone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9znjuljhpqvown299dj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9znjuljhpqvown299dj.jpg" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The results were evaluated on a 4-point scale and displayed in the table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmv9ypbbevsf57ungivf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgmv9ypbbevsf57ungivf.png" alt="Image description" width="360" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/@ericblade/quagga2"&gt;@ericblade/quagga2&lt;/a&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Free&lt;/li&gt;
&lt;li&gt;Weekly Downloads - 16000&lt;/li&gt;
&lt;li&gt;The new version of quagga is just now being developed and maintained&lt;/li&gt;
&lt;li&gt;Works well, but needs tweaking and testing&lt;/li&gt;
&lt;li&gt;Many different settings, integrates quickly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since it is free, it also showed itself poorly in tests, worse than the rest&lt;br&gt;
You can try it &lt;a href="https://serratus.github.io/quaggaJS/v1.0.0-beta.1/examples/multiple/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobt1uzvcy17qq39tgdkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobt1uzvcy17qq39tgdkw.png" alt="Image description" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.npmjs.com/package/html5-qrcode"&gt;html5 qrcode&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://scanapp.org/#reader"&gt;You can test it here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weekly Downloads - 12000&lt;/li&gt;
&lt;li&gt;Free&lt;/li&gt;
&lt;li&gt;Big community&lt;/li&gt;
&lt;li&gt;Powerful enough&lt;/li&gt;
&lt;li&gt;Easy to implement&lt;/li&gt;
&lt;li&gt;Flexible setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgxawpm2rr46vzkvhxwf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgxawpm2rr46vzkvhxwf.png" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.dynamsoft.com/barcode-reader/sdk-javascript/"&gt;dynamsoft-javascript-barcode&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/dynamsoft-javascript-barcode"&gt;https://www.npmjs.com/package/dynamsoft-javascript-barcode&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: paid&lt;br&gt;
10,000 barcode scan bundle - $1,249&lt;br&gt;
50,000 barcode scan bundle - $2,999&lt;br&gt;
100,000 barcode scan bundle - $4,999&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At first glance, less flexible, but everything you need is out of the box.&lt;/li&gt;
&lt;li&gt;It takes a little longer to set up than other paid options.&lt;/li&gt;
&lt;li&gt;Weekly Downloads - 9000&lt;/li&gt;
&lt;li&gt;It's solutions for various platforms and languages and supports many different code formats.&lt;/li&gt;
&lt;li&gt;7-day free period to try&lt;/li&gt;
&lt;li&gt;You can test it &lt;a href="https://demo.dynamsoft.com/barcode-reader-js/"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Actually, it doesn't work in Safari version 13 and below. But such users are less than 0.5%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falwxfnhsjc1z9xt71xba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falwxfnhsjc1z9xt71xba.png" alt="Image description" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://scanbot.io"&gt;scanbot.io&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Paid: $25,000 per year&lt;/li&gt;
&lt;li&gt;A young library, so I did not pay attention to it.&lt;/li&gt;
&lt;li&gt;They have not had time to promote it yet, so a very small community. There are few stars on GitHub. And few downloads.&lt;/li&gt;
&lt;li&gt;Large library size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is a &lt;a href="https://scanbot.io/en/sdk/demo/web-sdk#test"&gt;demo&lt;/a&gt; where you can test &lt;/li&gt;
&lt;li&gt;There is a trial license for 7 days.&lt;/li&gt;
&lt;li&gt;With many versions for different devices, it is frequently updated and supported.&lt;/li&gt;
&lt;li&gt;It works fast enough, not inferior to scandit-sdk. But there are no on-screen prompts and there is a little lack of interactivity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although it performed best in the tests, I would put it in second place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkchvr5588ni95chfy8nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkchvr5588ni95chfy8nf.png" alt="Image description" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the Oscar goes...&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://www.scandit.com/products/barcode-scanning/"&gt;scandit-sdk&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/scandit-sdk"&gt;https://www.npmjs.com/package/scandit-sdk&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: Paid solution, $25,000 per year&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a popular library&lt;/li&gt;
&lt;li&gt;Weekly Downloads - 47,000&lt;/li&gt;
&lt;li&gt;Easy to implement, with many functions out of the box&lt;/li&gt;
&lt;li&gt;Maybe not be as flexible as quagga2, but powerful and works with different kinds of codes.&lt;/li&gt;
&lt;li&gt;There are solutions for different platforms&lt;/li&gt;
&lt;li&gt;Showed good results in tests.&lt;/li&gt;
&lt;li&gt;You can test it &lt;a href="https://websdk.scandit.com"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivmhua0d39i7diah006o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivmhua0d39i7diah006o.png" alt="Image description" width="752" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Everything very much depends on the camera, device, browser, lighting, code size, and quality.&lt;br&gt;
Of course, paid ones work faster, more reliably, and better, but free ones are also not much inferior to them.&lt;br&gt;
Scandit-sdk seemed to me the best lib, it recognized the maximum number of codes on all devices and dealt with them very quickly. It is flexible but also expensive.&lt;/p&gt;

&lt;p&gt;Other paid options showed no worse results and also deserve attention.&lt;/p&gt;

&lt;p&gt;Among the free options, the Html5-code lib showed itself better, on Android in Chrome it was almost as good as paid solutions, but showed itself a little worse.&lt;br&gt;
Of the four, Quagga2 screwed up the most. Although it is flexibly configured and looks good, it recognized the codes the least of all.&lt;/p&gt;

&lt;p&gt;The article does not claim objectivity. The list of libraries may not be complete, so if you know of other libraries, feel free to comment.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>barcode</category>
      <category>scanner</category>
    </item>
    <item>
      <title>From Callback Hell to Promise Chains</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Fri, 07 Apr 2023 12:49:18 +0000</pubDate>
      <link>https://forem.com/yurich84/from-callback-hell-to-promise-chains-7hd</link>
      <guid>https://forem.com/yurich84/from-callback-hell-to-promise-chains-7hd</guid>
      <description>&lt;p&gt;When programming in JavaScript, we often have to make requests to the server. And as we know, the JS machine does not wait for the request to be done and continues to execute the next code. This approach in JS is called asynchrony.&lt;br&gt;
All requests to the server are promises. Although they do not return any result at the same time, they promise that they will return something, or they will throw an error.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal4mlfkujo7peuh4gncu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fal4mlfkujo7peuh4gncu.gif" alt="Image description" width="498" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to consider an example of when we need to make several requests to the server or call several promises. Let's create an array of promises.&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;promises&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
   &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="p"&gt;...&lt;/span&gt;
   &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I just want to call all these promises from a regular loop&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="k"&gt;for &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;promise&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;r&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 it will work if we don't have to wait for the result. But most likely we need the data that returns the promises. A special case may be when each subsequent promise must depend on the data of the previous one.&lt;br&gt;
The first thing that comes to mind is to call each subsequent promise in the &lt;code&gt;.then&lt;/code&gt; method of the previous one.&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;promises&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;promises&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;promises&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If you continue to nest promises one inside the other, then such code will be very difficult to read. And only indents help to orientate a little. This approach creates &lt;strong&gt;Callback Hell&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fver392lsurwtxffgdiu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fver392lsurwtxffgdiu0.png" alt="Image description" width="637" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, it would be better if the promise returns another promise. So this code can be reformatted in the &lt;strong&gt;promise chain&lt;/strong&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;promises&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&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;promises&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&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;promises&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="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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;result&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 approach is much more readable and resembles the Chain of Responsibilities design pattern.&lt;/p&gt;

&lt;p&gt;But when working with arrays, it is still easier and clearer to &lt;strong&gt;use loops&lt;/strong&gt;. Let's do it. To do this, we need to create a separate function and use the &lt;code&gt;async/await&lt;/code&gt; syntax.&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;run&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="k"&gt;for &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;promise&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;promises&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promise&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;result&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;run&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 much shorter and clearer. This approach will work in most cases and will be understandable to a developer of any level.&lt;/p&gt;

&lt;p&gt;The fact is that all promises are executed synchronously one after the other and it takes more time than if all requests were executed simultaneously. And in the case when the next promise does not depend on the previous one, and we want to work with the results of all requests, it is better to use special methods &lt;a href="https://javascript.info/promise-api#promise-all"&gt;all&lt;/a&gt;, &lt;a href="https://javascript.info/promise-api#promise-allsettled"&gt;allSettled&lt;/a&gt;, &lt;a href="https://javascript.info/promise-api#promise-race"&gt;race&lt;/a&gt;, &lt;a href="https://javascript.info/promise-api#promise-any"&gt;any&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's redesign this functionality so that it works more efficiently.&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;responses&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="k"&gt;for &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;response&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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 much better, and &lt;strong&gt;all promises inside &lt;code&gt;Promise.all&lt;/code&gt;&lt;/strong&gt; are executed asynchronously.&lt;br&gt;
We have considered several approaches to working with the array of promises and their main pros and cons.&lt;br&gt;
I hope this article helps you better understand promises and write better code.&lt;/p&gt;

</description>
      <category>promise</category>
      <category>javascript</category>
      <category>asynchrony</category>
      <category>programming</category>
    </item>
    <item>
      <title>Laravel MailGun with template, tags, and variables</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Tue, 04 Apr 2023 22:16:05 +0000</pubDate>
      <link>https://forem.com/yurich84/laravel-mailgun-with-template-tags-and-variables-2591</link>
      <guid>https://forem.com/yurich84/laravel-mailgun-with-template-tags-and-variables-2591</guid>
      <description>&lt;p&gt;Laravel is a great framework with a large ecosystem. There you can find tools for various services. But sometimes official libraries, and even more so unofficial ones, do not have all the functionality we need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mailgun.com/"&gt;Mailgun&lt;/a&gt; is one of the popular email services and Laravel has a &lt;a href="https://laravel.com/docs/mail#mailgun-driver"&gt;driver&lt;/a&gt; to use this service. Although Mailgun has a powerful tool for managing templates, such an option is not included in the library.&lt;br&gt;
I found other &lt;a href="https://prawnstar.medium.com/how-we-send-mailgun-template-emails-in-laravel-16105068c516"&gt;libraries&lt;/a&gt; on the Internet that offer work with templates, but I wanted to work with the official library and use Mail class. That's why I decided to add the create &lt;code&gt;Mailgun&lt;/code&gt; trait that expands the capabilities of the library.&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;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Traits&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;trait&lt;/span&gt; &lt;span class="nc"&gt;Mailgun&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;template&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;'general'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withSymfonyMessage&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;$message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHeaders&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;addTextHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X-Mailgun-Template-Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withSymfonyMessage&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;$message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHeaders&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;addTextHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X-Mailgun-Variables'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;json_encode&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;=&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;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;withSymfonyMessage&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;$message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHeaders&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;addTextHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'X-Mailgun-Tag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect this trait to the mail class and now we have the &lt;code&gt;template&lt;/code&gt;, &lt;code&gt;tag&lt;/code&gt;, and &lt;code&gt;variable&lt;/code&gt; methods available.&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;MessageMail&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Mailable&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ShouldQueue&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Queueable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SerializesModels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Mailgun&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="cd"&gt;/**
    * Create a new message instance.
    *
    * @return void
    */&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="cd"&gt;/**
    * Build the message.
    *
    * @return $this
    */&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;
           &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Email Subject'&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;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&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="nf"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'my_custom_tag'&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;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'mailgun_template'&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;variable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'link'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.url'&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;variable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope that soon such an opportunity will appear out of the box. Or I finally send a Pull Request.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>mailgun</category>
      <category>programming</category>
    </item>
    <item>
      <title>Communications between servers</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Sun, 02 Apr 2023 08:39:58 +0000</pubDate>
      <link>https://forem.com/yurich84/communications-between-servers-2ha5</link>
      <guid>https://forem.com/yurich84/communications-between-servers-2ha5</guid>
      <description>&lt;p&gt;In today's interconnected world, communication between servers is essential for businesses to operate smoothly. Whether it's transferring data, executing commands, or exchanging messages, there are several ways to communicate between servers. This article will discuss the most common ways to communicate between servers and the protocols on which each one is based.&lt;/p&gt;




&lt;h2&gt;
  
  
  Protocols
&lt;/h2&gt;

&lt;h3&gt;
  
  
  HTTP/HTTPS
&lt;/h3&gt;

&lt;p&gt;The Hypertext Transfer Protocol (HTTP) and its secure version (HTTPS) are the most common protocol for server communication. They are used to exchange data between web servers and clients, and can also be used for server-to-server communication. HTTP and HTTPS are best suited for web-based applications and APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  FTP/SFTP
&lt;/h3&gt;

&lt;p&gt;The File Transfer Protocol (FTP) and its secure version (SFTP) are commonly used for transferring files between servers. FTP is best suited for transferring large files or batches of files that do not need to be transmitted in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSH
&lt;/h3&gt;

&lt;p&gt;Secure Shell (SSH) is a protocol for securely connecting to remote servers and executing commands. SSH is best suited for managing servers and executing commands on them.&lt;/p&gt;

&lt;h3&gt;
  
  
  TCP/IP
&lt;/h3&gt;

&lt;p&gt;Transmission Control Protocol (TCP) and Internet Protocol (IP) are the most common protocols for transferring data between servers over the internet. TCP/IP is best suited for real-time applications that require fast, reliable communication.&lt;/p&gt;

&lt;h3&gt;
  
  
  UDP
&lt;/h3&gt;

&lt;p&gt;User Datagram Protocol. It is a connectionless, lightweight transport layer protocol that is used to send and receive datagrams over a network. UDP is a member of the Internet Protocol (IP) suite, and it is often used in applications where speed and efficiency are more important than reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technologies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Message Queues
&lt;/h3&gt;

&lt;p&gt;Message Queuing provides a mechanism for asynchronous communication between servers. Message Queues can be used to decouple processes, distribute work across multiple machines and recover from failures. Message Queues are best suited for applications that require high reliability and fault tolerance.&lt;/p&gt;

&lt;h3&gt;
  
  
  WebSockets
&lt;/h3&gt;

&lt;p&gt;WebSockets are a protocol for two-way communication between a client and a server over a single TCP connection. WebSockets can be used to provide real-time communication between servers. WebSockets are best suited for applications that require real-time data exchange, such as online games, chat applications, and financial trading systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  API calls
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;REST&lt;/strong&gt; (Representational State Transfer) is an architectural style for building web services that uses HTTP methods to retrieve and manipulate data. RESTful APIs are commonly used for communication between web services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SOAP&lt;/strong&gt; (Simple Object Access Protocol) is a messaging protocol that defines how XML-based messages are exchanged between web services. It uses XML to encode the message and HTTP as the transport protocol.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL&lt;/strong&gt; is a query language for APIs that was developed by Facebook. It allows clients to specify the data they need and receive only that data, reducing the amount of unnecessary data transfer between services.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Remote Procedure Calls (RPC)
&lt;/h3&gt;

&lt;p&gt;RPCs allow one server to call a method on another server as if it were a local method call. RPCs can be implemented using various protocols like HTTP, TCP, and UDP. RPCs are best suited for applications that require high performance and low latency, such as scientific simulations and financial trading systems.&lt;/p&gt;




&lt;p&gt;In conclusion, there are several ways to communicate between servers, and the choice of communication method depends on the specific use case and the requirements of the system. Message Queues, WebSockets, API calls, and RPCs are all viable options depending on the application's needs. By understanding the strengths and weaknesses of each communication method, businesses can choose the most appropriate one for their specific use case, resulting in faster and more reliable communication between servers.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>servers</category>
      <category>communications</category>
      <category>architecture</category>
    </item>
    <item>
      <title>How to speed up your web application</title>
      <dc:creator>Yurich</dc:creator>
      <pubDate>Sun, 26 Mar 2023 22:49:10 +0000</pubDate>
      <link>https://forem.com/yurich84/how-to-speed-up-your-web-application-52m0</link>
      <guid>https://forem.com/yurich84/how-to-speed-up-your-web-application-52m0</guid>
      <description>&lt;p&gt;It often happens that with the growth of the code base, the web application (site) starts to work more slowly. The page takes a long time to load. All of this annoys the end user, causing churn and less popularity. On the Internet, you can find many tips and ways to eliminate this deficiency. But I will also give some non-standard solutions that can be very appropriate in certain situations. I want to encourage the reader to make an optimized app from the very beginning.&lt;/p&gt;

&lt;p&gt;It all depends on the type of web application and the specific situation, but I will tell you how to make the web application faster and more responsive. I divided the optimization of the web application into two parts: front-end optimization and back-end optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Front-end optimization
&lt;/h2&gt;

&lt;p&gt;Everything you need to optimize from the point of view of search engines will tell you &lt;a href="https://pagespeed.web.dev/"&gt;https://pagespeed.web.dev/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Images compression
&lt;/h3&gt;

&lt;p&gt;The user does not need pictures in the maximum quality, it is enough that they are sharp. To achieve even greater results, you can convert images to WebP format, files in this format are 26% smaller than jpeg.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduce the number of requests to the server
&lt;/h3&gt;

&lt;p&gt;That is, combine all js files into one file or make them all download in parallel. The same for CSS files. Reduce the amount of icons using inline icons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minification JS, CSS, HTML
&lt;/h3&gt;

&lt;p&gt;Webpack minifies JS and CSS files by default when we build them in production mode. But it does not remove useless styles or classes. For this, you can use libraries like &lt;a href="https://purgecss.com/"&gt;https://purgecss.com/&lt;/a&gt;&lt;br&gt;
Do not forget to check the dependency, connect only the functionality that you use.&lt;/p&gt;
&lt;h3&gt;
  
  
  Browser’s cache
&lt;/h3&gt;

&lt;p&gt;PWA is one of the tools that allows you to cache your data in the browser to the extent that you can work with the web application completely without the Internet. But if you don't want to dive into it too much, you can just set the Expires HTTP header and the static files will be automatically cached in the browser.&lt;br&gt;
You can also use Local Storage, Cookies, Session storage, IndexedDB, Web SQL, Cache storage as you see fit. The different storages have its advantages and disadvantages.&lt;/p&gt;
&lt;h3&gt;
  
  
  Web sockets
&lt;/h3&gt;

&lt;p&gt;Websocket is a very powerful technology that allows you to listen to the server and update the data coming from the server in real time. They allow you to reduce the number of requests to the server and change small pieces of data with it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Lazy loading
&lt;/h3&gt;

&lt;p&gt;It is not necessary to download all the content of the page at once. Content that is off-screen, inside accordions, tabs, or otherwise hidden can be loaded later using AJAX requests or websockets.&lt;br&gt;
Keep in mind that this can affect the indexing of pages by search engines, although they say that they know how to work with such pages.&lt;/p&gt;
&lt;h3&gt;
  
  
  CDN
&lt;/h3&gt;

&lt;p&gt;The closer the end user is to the server, the faster the content will be loaded, so it makes more sense to put static data on a CDN server.&lt;br&gt;
In short, a CDN is a group of servers to which your files are duplicated. These servers are located in different geographical areas and when requested, the user receives files from the nearest one.&lt;/p&gt;
&lt;h2&gt;
  
  
  Backend optimization
&lt;/h2&gt;
&lt;h3&gt;
  
  
  OpCache
&lt;/h3&gt;

&lt;p&gt;If you're developing in PHP, you can safely enable it in most cases.&lt;br&gt;
Since the code of the entire site does not change so quickly, it does not need to be constantly compiled from scratch. PHP can cache already compiled code, which makes his work much faster.&lt;/p&gt;
&lt;h3&gt;
  
  
  Zip or Gzip compression
&lt;/h3&gt;

&lt;p&gt;Web servers such as apache and nginx can compress data on the fly.&lt;/p&gt;

&lt;p&gt;It could be easily done with Nginx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    ...
    gzip off;
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two modules are responsible for compression in Apache. The first module is called mod_deflate and the second mod_gzip, only one of them needs to be enabled. But this puts an additional load on the server. With mod_gzip, you need to compress each file yourself and upload it to the site root.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database optimization
&lt;/h3&gt;

&lt;p&gt;Usually, the server itself works quickly and in most cases, the long response of the server occurs due to heavy and numerous requests to the database.&lt;br&gt;
In this case, it is necessary to check whether the N+1 request problem does not arise for example when the requests occur in a cycle. If this problem is fixed, it is necessary to check whether all the necessary indexes are inserted. Database optimization is a separate big topic, which I will not spotlight on in this article.&lt;br&gt;
Data handling approaches such as data caching and queuing some requests play an important role. I will talk about this in detail in the next two points.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data caching
&lt;/h3&gt;

&lt;p&gt;Most of the data changes infrequently enough that it will be correct to cache it using high-speed data stores. Depending on the speed, reliability, cost, and amount of data, there are different storages, such as File, Memcache, Redis, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Queues
&lt;/h3&gt;

&lt;p&gt;All functionality that is not required to work at the same moment when the request is made must be queued.&lt;br&gt;
For example, we save the order, and as a result - we need to get the order number. Saving the order in the database, transferring information about it to the managers via a third-party API, sending a letter to the client and the store administrator - all this functionality must be queued. This will help not only to unload the server but also to reduce the load on the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scaling
&lt;/h3&gt;

&lt;p&gt;If none of this helps, maybe the server simply does not cope with a large load, then you need to take a more powerful server. This is the simplest scaling (vertical scaling).&lt;br&gt;
But eventually, you need to think about horizontal scaling. It is also different, depending on where the load is most significant. Raise several server instances and install a load balancer to balance the load between these servers. But suppose there are bottlenecks where the server's capacity is used to the maximum, such as rendering, conversions or file generation, etc. In that case, such functionality is transferred to a separate service, which, in turn, will be scaled separately. There are now many tools and services that can automatically scale your app according to its load.&lt;br&gt;
There is also an option to switch to serverless technology, which will allow you not to think about scaling. &lt;br&gt;
It also happens that it is necessary to scale the database horizontally, in this case, different replication approaches are used.&lt;/p&gt;

&lt;p&gt;I described the main solutions that can improve the speed of the web application. In any case, it is necessary to look for a problem and choose approaches, taking into account the type of web application, its structure, and its purpose.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>seo</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
