<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gaurav Makhecha</title>
    <description>The latest articles on DEV Community by Gaurav Makhecha (@gauravmak).</description>
    <link>https://dev.to/gauravmak</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%2F64929%2Fa2c41b8e-2f8d-414e-84ae-cbf3b3b0cdcb.png</url>
      <title>DEV Community: Gaurav Makhecha</title>
      <link>https://dev.to/gauravmak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gauravmak"/>
    <language>en</language>
    <item>
      <title>Why don't you start writing tests?</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Mon, 08 Aug 2022 07:28:00 +0000</pubDate>
      <link>https://dev.to/gauravmak/why-dont-you-start-writing-tests-5aj7</link>
      <guid>https://dev.to/gauravmak/why-dont-you-start-writing-tests-5aj7</guid>
      <description>&lt;p&gt;&lt;strong&gt;See how easy it is to get started with automated testing in Laravel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are hundreds of articles on &lt;a href="https://dev.to/flippedcoding/4-reasons-you-should-write-tests-first-47oa"&gt;why you should&lt;/a&gt; &lt;a href="https://dave.cheney.net/2019/05/14/why-bother-writing-tests-at-all" rel="noopener noreferrer"&gt;write tests&lt;/a&gt; &lt;a href="https://www.educative.io/answers/5-reasons-why-testing-code-is-great" rel="noopener noreferrer"&gt;for your code&lt;/a&gt;. And I assume you have read them many times.&lt;/p&gt;

&lt;p&gt;Many developers realize the importance of writing tests but just do not get started. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not
&lt;/h3&gt;

&lt;p&gt;Mainly because of some misunderstanding.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They face the fear of doing it wrong.&lt;/li&gt;
&lt;li&gt;They think they're not good enough (yet) to write tests.&lt;/li&gt;
&lt;li&gt;They are not sure which type of tests apply to their projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As someone who has been there, let me tell you these things are temporary. Once you start writing tests, all this will go away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not Today
&lt;/h3&gt;

&lt;p&gt;If I were to tell you that it would take only 5-10 minutes of your time to get started with testing, would you mind starting now?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let today be the start of something new.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;William Shakespeare&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay. So let's kick off our testing journey with a Laravel application. You may use an existing web application or create a new one.&lt;/p&gt;

&lt;p&gt;In fact, you can follow this article even for any other programming language/framework as we are going to discuss the high-level stuff only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default tests with Laravel
&lt;/h3&gt;

&lt;p&gt;Laravel comes with a couple of tests out of the box. Open your terminal and type:&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 &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you haven't messed anything up in your web app, you would be greeted with something like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzmj8tryemvdnwkk3t12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzmj8tryemvdnwkk3t12.png" alt="First tests with Laravel" width="500" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great, we have a perfect starting point. Let's write our own tests now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some web app code
&lt;/h3&gt;

&lt;p&gt;If you have a fresh new Laravel web application, please append the following code to the &lt;code&gt;routes/web.php&lt;/code&gt; file before writing your first test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// existing code...&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$validated&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;validate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'string'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'max:255'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'max:255'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'required'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'confirmed'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$validated&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;back&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'User created successfully.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following things are happening in this code: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We validate the form data.&lt;/li&gt;
&lt;li&gt;We create the user in the database. &lt;/li&gt;
&lt;li&gt;We redirect the user back with a success message. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And our tests should cover all these.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a new test file
&lt;/h3&gt;

&lt;p&gt;We'll start by creating a new test file. Please execute the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;A new test file should be created at &lt;code&gt;tests/Feature/UserTest.php&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heads up - Resetting the database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your code and tests play with the database, you should reset your database after each of your tests to ensure that one test cannot affect the results of another one. Laravel makes it effortless by providing a trait that you can add to your test classes.&lt;/p&gt;

&lt;p&gt;Please add the following trait in the &lt;code&gt;UserTest.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="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Foundation\Testing\LazilyRefreshDatabase&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;UserTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&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;LazilyRefreshDatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// existing code...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that done, let's bake tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your first test - the Happy path
&lt;/h3&gt;

&lt;p&gt;The default test file already covers a test for a GET request. Thus, we can directly write a test for a POST request.&lt;/p&gt;

&lt;p&gt;When the user submits the form from the browser, a POST request is made with the inputs and values. We are going to simulate the same thing in our tests.&lt;/p&gt;

&lt;p&gt;Please append the following code to the &lt;code&gt;UserTest.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="c1"&gt;// existing code...&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;test_new_user_can_be_added&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Gaurav'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'gauravmakhecha@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password_confirmation'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertRedirect&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;assertSessionHas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'User created successfully.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertDatabaseHas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Gaurav'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'gauravmakhecha@gmail.com'&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;Laravel provides an easy way to make a POST request from your test files using the &lt;code&gt;post()&lt;/code&gt; method. Using that, we make the request and verify that user details are added to the database and the response is a redirect with the proper message in the session.&lt;/p&gt;

&lt;p&gt;Wasn't this straightforward? Let's try one more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test for the validation
&lt;/h3&gt;

&lt;p&gt;How about adding a test to make sure that our validation works as expected? Please append the following code to the &lt;code&gt;UserTest.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="c1"&gt;// existing code...&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;test_new_user_data_is_validated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'not_email_format'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password_confirmation'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'456789'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;302&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;assertSessionHasErrors&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we pass invalid data for the form inputs and confirm (assert) that there is a redirect response (HTTP status code 302) and that there are &lt;a href="https://laravel.com/docs/9.x/http-tests#assert-session-has-errors" rel="noopener noreferrer"&gt;validation errors&lt;/a&gt; in the session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test for the unique email address
&lt;/h3&gt;

&lt;p&gt;The business requirement is that the email address of each user has to be unique so let us add a test for the same. Append this test to the &lt;code&gt;UserTest.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="c1"&gt;// existing code...&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;test_new_user_with_same_email_cannot_be_added&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'gauravmakhecha@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Gaurav'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'gauravmakhecha@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'password_confirmation'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'123456'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;302&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;assertSessionDoesntHaveErrors&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&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;assertSessionHasErrors&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test uses &lt;a href="https://laravel.com/docs/9.x/database-testing#defining-model-factories" rel="noopener noreferrer"&gt;Laravel Factory&lt;/a&gt; to add a user to the database and then tries to make a POST request with the same email address. Let us run tests and see the results.&lt;/p&gt;

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

&lt;p&gt;Oops, it failed. And the reason? We missed adding the unique validation in our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now your test is guiding you with the development. (Yes TDD!)&lt;/p&gt;

&lt;p&gt;Please make the following update in the &lt;code&gt;routes/web.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;-        'email' =&amp;gt; ['required', 'email', 'max:255'],
&lt;/span&gt;&lt;span class="gi"&gt;+        'email' =&amp;gt; ['required', 'email', 'max:255', 'unique:users'],
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once updated, give yourself a pat on the back and run the tests again (&lt;code&gt;php artisan test&lt;/code&gt;)&lt;/p&gt;

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

&lt;h3&gt;
  
  
  What more?
&lt;/h3&gt;

&lt;p&gt;Did you realize you are now officially a developer who writes automated tests? Congrats!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgdkuoq58np5100xeo53.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzgdkuoq58np5100xeo53.gif" alt="Congrats!" width="546" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Need more examples? Check &lt;a href="https://github.com/laravel/breeze/blob/master/stubs/default/tests/Feature" rel="noopener noreferrer"&gt;this directory&lt;/a&gt; from the official Laravel repository for tests related to various modules.&lt;/p&gt;

&lt;p&gt;The goal of this article is just to get you started with writing tests. Not to cover different use cases or scenarios. Hence, I limit the practical coding here and would like to share a few other things to help you progress with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Patterns that can help you
&lt;/h3&gt;

&lt;p&gt;Many developers aren't sure for which parts of their code should they write tests. The simplest answer is: Try to write automated tests for all the functionality that you check while manually testing your web app.&lt;/p&gt;

&lt;p&gt;In this example, we would have checked the DB entry, the validation messages, and the redirect while manually testing the web app. And that is what our automated tests covered.&lt;/p&gt;

&lt;p&gt;Here are a couple of patterns to help you plan your tests:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Given-When-Then&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Arrange-Act-Assert&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both are similar so you can use any of them. The idea is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, you set the scene (Add existing DB records, log in a user, etc.)&lt;/li&gt;
&lt;li&gt;Then you take an action (Visit a URL, submit a form, etc.)&lt;/li&gt;
&lt;li&gt;Finally, you verify the results/effects (A DB entry, a session call, response status code, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way can generally help you in writing most of the test cases. &lt;/p&gt;

&lt;p&gt;Moreover, we have a dedicated article about &lt;a href="https://blog.freshbits.in/write-tests-only-for-your-own-code" rel="noopener noreferrer"&gt;writing tests only for your code&lt;/a&gt; to guide you around the test boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  (Not so) Complex Stuff
&lt;/h3&gt;

&lt;p&gt;What we covered in this article are &lt;em&gt;Feature&lt;/em&gt; tests. There are many other types of tests (Unit tests, Feature tests, Integration tests, Acceptance tests, etc.).&lt;/p&gt;

&lt;p&gt;Do not hurry to learn/use all of them, you don't have to. You will feel the need yourself if/when the time arrives.&lt;/p&gt;

&lt;p&gt;Topics like &lt;em&gt;mocking&lt;/em&gt; and &lt;em&gt;stubbing&lt;/em&gt; fall in the same category. Believe me, it is not compulsory to use them. But keep in mind they are &lt;em&gt;quite handy&lt;/em&gt; for medium to big-size projects. We use them in our projects and can't live without them.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Note on PEST
&lt;/h3&gt;

&lt;p&gt;We use &lt;a href="https://pestphp.com/" rel="noopener noreferrer"&gt;PEST&lt;/a&gt; for writing tests but I decided not to include that in this article to keep things simple. I wish (and am sure) it would come out of the box with Laravel.&lt;/p&gt;

&lt;h3&gt;
  
  
  To The Moon
&lt;/h3&gt;

&lt;p&gt;I hope this article gets you started with writing tests and you never stop in the future. Feel free to comment below in case of any questions. May those tools give you more testing features 😉&lt;/p&gt;

&lt;p&gt;And if any of your friends are also giving excuses to start writing tests, how about sharing this article with them for the push?&lt;/p&gt;

&lt;p&gt;Cheers and regards.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tdd</category>
      <category>php</category>
      <category>laravel</category>
    </item>
    <item>
      <title>An easier way to manage HTML DOM using Javascript</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Fri, 15 Apr 2022 14:37:08 +0000</pubDate>
      <link>https://dev.to/gauravmak/an-easier-way-to-manage-html-dom-using-javascript-4775</link>
      <guid>https://dev.to/gauravmak/an-easier-way-to-manage-html-dom-using-javascript-4775</guid>
      <description>&lt;p&gt;Why you should use HTML Code generation methods as a last resort&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Training&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We hire freshers and train them in-house here at &lt;a href="http://freshbits.in" rel="noopener noreferrer"&gt;Freshbits&lt;/a&gt;. A lot of our own learning happens when we teach basic stuff to them.&lt;/p&gt;

&lt;p&gt;Out of that, one of the random &lt;a href="https://blog.freshbits.in/the-correct-way-to-pass-methods-as-event-handlers-in-javascript" rel="noopener noreferrer"&gt;basic stuff&lt;/a&gt; that I would like to share today is about HTML code generation using Javascript.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We get the beginners to add some interactivity to the HTML pages that they have built using Javascript. It could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add to cart functionality on the e-commerce page&lt;/li&gt;
&lt;li&gt;Delete item functionality on the products listing page&lt;/li&gt;
&lt;li&gt;Add address functionality on the checkout page, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Javascript frameworks like React, Vue, or Angular are not in their syllabus yet. They use jQuery or vanilla JS for these kinds of developments.&lt;/p&gt;

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

&lt;p&gt;With the fresh opportunity on hand and &lt;em&gt;limited&lt;/em&gt; working experience, they are generally excited to go for it and come up with something like the following.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The go-to old way 💩&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I will take the code done by our newest team member, Utsav, as an example. He was given the task of coding the &lt;em&gt;add to cart&lt;/em&gt; functionality. As we expected, he coded the functionality this way:&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;function&lt;/span&gt; &lt;span class="nf"&gt;displayCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Abbreviating other stuff to focus on the core topic...&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;imageTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;imageTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;imageTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;w-10 h-10 object-cover rounded-md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-item-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nameTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;span&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;nameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ml-4 font-semibold text-sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;nameTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-item-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;priceTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;priceTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-item-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deleteTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;deleteTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;px-3 py-1 rounded-md bg-red-300 text-white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;deleteTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;onclick&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;removeFromCart(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;deleteTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-item-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deleteTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There is nothing wrong with this approach. It is just &lt;strong&gt;less readable and maintainable&lt;/strong&gt;. What if we want to add more elements to this cart? What if we wish to change styles?&lt;/p&gt;

&lt;p&gt;Some might argue jQuery can make it better. While those long lines of code would be shorter, the main issue still stays there: &lt;em&gt;managing changes in the final HTML output&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Reading and modifying the HTML directly is easier. Let's see how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another way 🙅&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can rewrite the same example as the following:&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;function&lt;/span&gt; &lt;span class="nf"&gt;displayCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Abbreviating other stuff to focus on the core topic...&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;cartItemHtml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;div id="cart-item-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;img class="w-10 h-10 object-cover rounded-md" src="&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;" /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;span class="ml-4 font-semibold text-sm"&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;button class="px-3 py-1 rounded-md bg-red-300 text-white" onclick="removeFromCart(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;)"&amp;gt;x&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;There is much better readability now. We can see what the final HTML is gonna look like. But, the HTML code is merged into Javascript so we have to play with those quotes a lot. One step further is to make the HTML code independent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even better way 🤗&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template" rel="noopener noreferrer"&gt;template&lt;/a&gt; HTML tag that is not shown on the page by default. We can use it to host our HTML code like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"cart-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-10 h-10 object-cover rounded-md cart-item-image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ml-4 font-semibold text-sm cart-item-name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cart-item-price"&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;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"px-3 py-1 rounded-md bg-red-300 text-white cart-item-delete"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;x&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks like the code we can easily maintain, right? Now how do we use it in the Javascript you asked?&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;function&lt;/span&gt; &lt;span class="nf"&gt;displayCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Abbreviating other stuff to focus on the core topic...&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cart-item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;cartItemTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;cartItemTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img.cart-item-image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="nx"&gt;cartItemTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;span.cart-item-name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;cartItemTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div.cart-item-price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;cartItemTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button.cart-item-delete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;removeFromCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, our Javascript can directly target each element inside the template and set the attributes and content respectively.&lt;/p&gt;

&lt;p&gt;Is there any way to take this one step further? If you have any ideas, please do share.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wind up&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This learning is mainly for beginners when they are getting started with HTML and Javascript. As they progress, there are more options like using &lt;a href="https://colorlib.com/wp/top-templating-engines-for-javascript" rel="noopener noreferrer"&gt;templating engines&lt;/a&gt; or going with full-fledged &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks" rel="noopener noreferrer"&gt;JS frameworks&lt;/a&gt; where you manage the data and the framework takes care of the DOM updates via reactivity.&lt;/p&gt;

&lt;p&gt;That's it. If you have some JS code generating HTML, try the template tag today and let us know how it goes. See you on the flip side.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Credits: Cover Photo by &lt;a href="https://unsplash.com/@halacious?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Hal Gatewood&lt;/a&gt; on &lt;a href="https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>html</category>
      <category>dom</category>
      <category>template</category>
    </item>
    <item>
      <title>Write tests only for your own code</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Sat, 09 Apr 2022 14:51:58 +0000</pubDate>
      <link>https://dev.to/gauravmak/write-tests-only-for-your-own-code-1hd</link>
      <guid>https://dev.to/gauravmak/write-tests-only-for-your-own-code-1hd</guid>
      <description>&lt;p&gt;Real-life example to answer 'what should I test?'&lt;/p&gt;

&lt;p&gt;The developers who are just getting started with writing tests often get confused about what to test and how to test it &lt;em&gt;'properly'&lt;/em&gt;. Terms like Feature tests, Unit tests, Integration tests, and Acceptance tests are overwhelming.&lt;/p&gt;

&lt;p&gt;But It's easier than most people think. You just need to write the test code that confirms whether your web app code does what it is supposed to do. Nothing more, nothing less.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Let's take an example to make it clear. We have an open-source package called &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer" rel="noopener noreferrer"&gt;Laravel Log Enhancer&lt;/a&gt; that adds contextual data to the Laravel log entries.&lt;/p&gt;

&lt;p&gt;The default Laravel log entry looks something like this:&lt;/p&gt;

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

&lt;p&gt;And the package improves it to:&lt;/p&gt;

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

&lt;p&gt;This package has been downloaded 222k+ times but let me tell you a secret 🤫. It is just connecting the dots and has a tiny codebase.&lt;/p&gt;

&lt;p&gt;Laravel uses the &lt;a href="https://github.com/Seldaek/monolog" rel="noopener noreferrer"&gt;Monolog&lt;/a&gt; library to manage the logging module. And Monolog offers something called &lt;a href="https://seldaek.github.io/monolog/doc/01-usage.html#using-processors" rel="noopener noreferrer"&gt;processors&lt;/a&gt; to add extra data for all the log entries.&lt;/p&gt;

&lt;p&gt;Okay, with the introduction out of our way, we can take a look at some 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="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$logger&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHandlers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'laravel_log_enhancer.log_request_details'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;pushProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WebProcessor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'laravel_log_enhancer.log_memory_usage'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;pushProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MemoryUsageProcessor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;pushProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RequestDataProcessor&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 piece of code is the heart of the package. Based on the configuration, it is &lt;em&gt;just&lt;/em&gt; pushing the processor(s) to the Monolog handlers. The rest of the work is done by the Monolog library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tests for our example
&lt;/h3&gt;

&lt;p&gt;Theoretically, our log enhancer package is supposed to add extra data to the log entries. Hence we should write automated tests that verify that behavior. Right?&lt;/p&gt;

&lt;p&gt;Should it be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/** @test */&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;it_adds_extra_data_to_the_log_entries&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Given&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;'laravel_log_enhancer.log_memory_usage'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&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;'laravel_log_enhancer.log_request_details'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// When&lt;/span&gt;
    &lt;span class="c1"&gt;// Run the code that logs something&lt;/span&gt;

    &lt;span class="c1"&gt;// Then&lt;/span&gt;
    &lt;span class="c1"&gt;// Fetch the log entry and check whether extra details are present in it&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No!!&lt;/p&gt;

&lt;p&gt;The package is only pushing some processors to the handlers. It shouldn't worry about what happens to the final log entry. It is the responsibility of the Monolog tests to verify that part. Makes sense? Good.&lt;/p&gt;

&lt;p&gt;With that understanding, let's take a look at the actual test code from the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/** @test */&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;it_adds_respective_processors_to_the_log_handler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'laravel_log_enhancer.log_memory_usage'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&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;'laravel_log_enhancer.log_request_details'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nv"&gt;$logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nv"&gt;$handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$logger&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getHandlers&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;$handlers&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertInstanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RequestDataProcessor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;popProcessor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertInstanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MemoryUsageProcessor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;popProcessor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertInstanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WebProcessor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$handler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;popProcessor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test is confirming exactly what our package is doing: adding processors to the handlers. Nothing more, nothing less.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rest
&lt;/h3&gt;

&lt;p&gt;I hope this example helps you decide the boundaries of your tests and increase your confidence in writing them.&lt;/p&gt;

&lt;p&gt;Do you have any other examples in mind that explain what to test? Feel free to comment and share. See you!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Credits - Cover Photo by &lt;a href="https://unsplash.com/@pawelskor?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Paul Skorupskas&lt;/a&gt; on &lt;a href="https://unsplash.com/@pawelskor?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tdd</category>
      <category>laravel</category>
      <category>logging</category>
    </item>
    <item>
      <title>Custom authentication guard in Laravel Sanctum</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Tue, 29 Mar 2022 14:47:17 +0000</pubDate>
      <link>https://dev.to/gauravmak/custom-authentication-guard-in-laravel-sanctum-315k</link>
      <guid>https://dev.to/gauravmak/custom-authentication-guard-in-laravel-sanctum-315k</guid>
      <description>&lt;p&gt;How to specify auth guard when using multiple guards with Sanctum&lt;/p&gt;

&lt;h3&gt;
  
  
  Preamble
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/sanctum" rel="noopener noreferrer"&gt;Laravel Sanctum&lt;/a&gt; is the go-to solution for token-based API authentication and SPA (Single page application) authentication. It uses an authentication guard when performing the SPA authentication.&lt;/p&gt;

&lt;p&gt;By default, the &lt;code&gt;web&lt;/code&gt; guard is used as per the &lt;a href="https://github.com/laravel/sanctum/blob/2.x/config/sanctum.php" rel="noopener noreferrer"&gt;configuration file&lt;/a&gt;. The same guard is used in the default Laravel &lt;a href="https://github.com/laravel/laravel/blob/9.x/config/auth.php" rel="noopener noreferrer"&gt;request authentication&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;If your web app has multiple &lt;code&gt;panels&lt;/code&gt; (say, admin, manager, customer, etc.), you'd be using multiple authentication guards. And there is a way to specify a guard to the auth middleware like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/setup'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only the users authenticated via the admin guard can visit this page.&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:admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But in the case of Sanctum, there is no way to specify the guard. The word &lt;code&gt;sanctum&lt;/code&gt; itself is used in the place of the guard name:&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;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/setup'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The default `web` guard is used. There is no option to specify any other guard name here.&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How do we use the non-default guard then? &lt;a href="https://stackoverflow.com/questions/62359429/laravel-sanctum-custom-guard" rel="noopener noreferrer"&gt;Many&lt;/a&gt; &lt;a href="https://laracasts.com/discuss/channels/laravel/sanctum-spa-multi-auth" rel="noopener noreferrer"&gt;developers&lt;/a&gt; &lt;a href="https://github.com/laravel/sanctum/issues/144" rel="noopener noreferrer"&gt;have&lt;/a&gt; faced this issue. Let's solve it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create a middleware&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will create a new middleware that will set the authentication guard for us based on the URL. Let us call it &lt;code&gt;SetSanctumGuard&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Middleware&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;Closure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SetSanctumGuard&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Closure&lt;/span&gt; &lt;span class="nv"&gt;$next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;startsWith&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;getRequestUri&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'/api/admin/'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'sanctum.guard'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;startsWith&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;getRequestUri&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'/api/manager/'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'sanctum.guard'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'manager'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;elseif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;startsWith&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;getRequestUri&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;'/api/customer/'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'sanctum.guard'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'customer'&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;$next&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;Assuming that our web app follows this pattern in the API endpoints, we can decide the auth guard dynamically inside the middleware. Or you can try any other way as per your web app scenario to decide the guard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Enable the middleware&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are multiple ways to specify a middleware. In this case, we can simply add it to the &lt;code&gt;api&lt;/code&gt; array inside the &lt;code&gt;app/Http/Kernel.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="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$middlewareGroups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'web'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="s1"&gt;'api'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;\App\Http\Middleware\SetSanctumGuard&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Add a note in the config file&lt;/strong&gt; (Optional)&lt;/p&gt;

&lt;p&gt;To assure that none of the team members (or even yourself) get surprises in the future, it is a good idea to note this in the &lt;code&gt;config/sanctum.php&lt;/code&gt; file. I do it like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'guard'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// This is set by the `SetSanctumGuard` middleware&lt;/span&gt;

    &lt;span class="c1"&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 with this,  your web app should be using the respective auth guard to protect the routes as per the user type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cheers
&lt;/h3&gt;

&lt;p&gt;I hope Sanctum allows this customization in the near future. And we will not need to create a custom middleware for this use case.&lt;/p&gt;

&lt;p&gt;Until then, enjoy this quick hack and build powerful Laravel web apps. Have fun!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Credits - Cover Photo by &lt;a href="https://unsplash.com/@glenncarstenspeters?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Glenn Carstens-Peters&lt;/a&gt; on &lt;a href="https://unsplash.com/@glenncarstenspeters?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>authentication</category>
      <category>programming</category>
    </item>
    <item>
      <title>PHP Namespaces are not the same as the Directory Structure</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Wed, 16 Mar 2022 14:46:03 +0000</pubDate>
      <link>https://dev.to/gauravmak/php-namespaces-are-not-the-same-as-the-directory-structure-160o</link>
      <guid>https://dev.to/gauravmak/php-namespaces-are-not-the-same-as-the-directory-structure-160o</guid>
      <description>&lt;p&gt;Let's start with a question: We have a PHP class &lt;em&gt;SalesController.php&lt;/em&gt; with the namespace &lt;code&gt;App/Http/Controllers&lt;/code&gt; and it is located at &lt;code&gt;app/Http/Controllers/SalesController.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where do you think the class &lt;em&gt;Sale.php&lt;/em&gt; with the namespace &lt;code&gt;App/Domain/Sales&lt;/code&gt; would be located?&lt;/p&gt;

&lt;p&gt;Did you say &lt;code&gt;app/Domain/Sales/Sale.php&lt;/code&gt;? Are you sure?&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;Well, it is located at &lt;code&gt;src/Domain/Sales/Sale.php&lt;/code&gt; and it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why so&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the &lt;a href="https://www.php-fig.org/psr/psr-4/" rel="noopener noreferrer"&gt;PSR-4&lt;/a&gt; autoloading, we can define the namespaces prefix and their corresponding base directories.&lt;/p&gt;

&lt;p&gt;Following is the composer configuration to clear the doubt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"autoload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"psr-4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"App\\Http\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"app/Http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"App\\Domain\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/Domain"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Reasoning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First of all, namespacing allows you to divide your code files into multiple groups. That allows you to set the same name for two different classes as far as they belong to different namespaces.&lt;/p&gt;

&lt;p&gt;This flexibility allows developers to follow their own conventions over the framework conventions keeping all the parties happy.&lt;/p&gt;

&lt;p&gt;One additional benefit when using namespaces in the code is easier directory renames. No need to do 'find &amp;amp; replace' in all the files that require your classes. Changing the base directory of the namespace does the job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fun Fact&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can set &lt;a href="https://www.php-fig.org/psr/psr-4/examples/#class-example" rel="noopener noreferrer"&gt;multiple base directories&lt;/a&gt; for a single namespace prefix. Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"autoload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"psr-4"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"Domain\\"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lib/"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not sure why one would go for this as it is a bit confusing. But it's possible, however.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Story ends&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In case you cannot find a class or directory by following the namespace words, do check the autoload config once. You may get the answer. Sayonara!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Credits - Cover Photo by &lt;a href="https://unsplash.com/@randyfath?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Randy Fath&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/randy-hath-chess?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>composer</category>
      <category>namespaces</category>
      <category>classes</category>
    </item>
    <item>
      <title>The correct way to pass Methods as Event Handlers in Javascript</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Thu, 10 Mar 2022 13:35:15 +0000</pubDate>
      <link>https://dev.to/gauravmak/the-correct-way-to-pass-methods-as-event-handlers-in-javascript-14i1</link>
      <guid>https://dev.to/gauravmak/the-correct-way-to-pass-methods-as-event-handlers-in-javascript-14i1</guid>
      <description>&lt;p&gt;&lt;em&gt;Those parentheses make a BIG difference and change the result&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One of my colleagues wasn't receiving the expected parameters in a JS method the other day. He was &lt;strong&gt;trying&lt;/strong&gt; to make a third-party Vue.js plugin work in a project (as we all do with fluctuating confidence).&lt;/p&gt;

&lt;p&gt;Let's go through a simple example with vanilla Javascript but the rule applies everywhere (including your favorite JS framework).&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;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;just-do-it&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;spreadHappiness&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;spreadHappiness&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You are awesome&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do you think will happen when a user clicks on that button?&lt;/p&gt;

&lt;p&gt;Guessed it?&lt;/p&gt;

&lt;p&gt;Nothing!&lt;/p&gt;

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

&lt;p&gt;The method gets called upon page load and nothing happens when the button is clicked. Hmm...&lt;/p&gt;

&lt;p&gt;Did you notice that we have put the parentheses &lt;code&gt;()&lt;/code&gt; after method name &lt;code&gt;spreadHappiness()&lt;/code&gt; in the first line?&lt;/p&gt;

&lt;p&gt;It is that classic &lt;em&gt;call-by-reference&lt;/em&gt; vs &lt;em&gt;call-by-value&lt;/em&gt; thing.&lt;/p&gt;

&lt;p&gt;That line should have been written like this (with parentheses removed):&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;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;just-do-it&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;spreadHappiness&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And with that, clicking on that button would log the statement in the browser console as expected.&lt;/p&gt;

&lt;p&gt;Now, did you know that the event handler receives an object based on the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event" rel="noopener noreferrer"&gt;&lt;code&gt;Event&lt;/code&gt;&lt;/a&gt; interface as a parameter? This means you can use the Event metadata in your method. Like so:&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;function&lt;/span&gt; &lt;span class="nf"&gt;spreadHappiness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&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;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// click&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, you should skip those parentheses when passing a method name as an event handler in most cases. When one needs to get the event handler dynamically, calling another method and returning it makes sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing
&lt;/h3&gt;

&lt;p&gt;In short, putting those parentheses after the method name while specifying the event handler &lt;strong&gt;is not&lt;/strong&gt; an optional thing. It changes the result.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;method():&lt;/em&gt; Executed instantly and the return value used as the event handler.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;method:&lt;/em&gt; Used as the event handler and it receives the parameters when called.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Again, &lt;em&gt;Doing a method call&lt;/em&gt; and &lt;em&gt;passing the method reference&lt;/em&gt; are two different things and developers, especially beginners, should be aware of this difference.&lt;/p&gt;

&lt;p&gt;Do any of your friends need to know this? Share this article with them to make their debugging life easier.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Calling Alpine.js methods from third-party scripts</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Tue, 08 Mar 2022 04:57:03 +0000</pubDate>
      <link>https://dev.to/gauravmak/calling-alpinejs-methods-from-third-party-scripts-2265</link>
      <guid>https://dev.to/gauravmak/calling-alpinejs-methods-from-third-party-scripts-2265</guid>
      <description>&lt;p&gt;&lt;em&gt;How we made Alpine-powered page understand Google Map events&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently, we faced a small challenge when implementing Google Map on an Alpine.js powered page. Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Map markers data is loaded in the Alpine.js store&lt;/li&gt;
&lt;li&gt;The Google Map is outside the Alpine.js scope so &lt;strong&gt;cannot call Alpine method directly&lt;/strong&gt; after its loaded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was no way we could show those map markers on the Google Map.&lt;/p&gt;

&lt;p&gt;After some surfing, &lt;a href="https://github.com/alpinejs/alpine/discussions/517" rel="noopener noreferrer"&gt;this thread&lt;/a&gt; gave a hint. Let us go through the actual code to set up the base.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Google Maps related code&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"google-map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 600px;"&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;/div&amp;gt;&lt;/span&gt;

...

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://maps.googleapis.com/maps/api/js?key=APIKEY&amp;amp;callback=renderMap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;googleMapObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;googleMapObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;google-map&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Map config&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;And here's the Alpine.js setup code&lt;/em&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alpine:init&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Alpine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;mapMarkers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="c1"&gt;// Pre-loaded markers data&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Events&lt;/em&gt; to the rescue. You can just fire a custom Javascript window event from the Google Maps object and make Alpine listen to it. Let's see the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderMap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// initialize map code&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;mapLoadedEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map-loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapLoadedEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we are firing the custom JS event called &lt;code&gt;map-loaded&lt;/code&gt; once the Google Map is loaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt; &lt;span class="na"&gt;x-data&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;map-loaded.window=&lt;/span&gt;&lt;span class="s"&gt;"$store.app.addAllMarkers()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"google-map"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"height: 600px;"&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;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This HTML code listens to that event and calls the &lt;em&gt;addAllMarkers&lt;/em&gt; Alpine method. With that, our Google Map can call the Alpine.js method to show the map markers.&lt;/p&gt;

&lt;p&gt;Lastly, our Alpine method can do the rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;googleMapObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alpine:init&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Alpine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;mapMarkers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="c1"&gt;// Pre-loaded markers data&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;

            &lt;span class="nf"&gt;addAllMarkers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mapMarkers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mapMarker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;google&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Marker&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                        &lt;span class="c1"&gt;// Map marker config&lt;/span&gt;
                    &lt;span class="p"&gt;});&lt;/span&gt;
                &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We did this for Google Maps but you can do the same with any other third-party JS library using the custom Javascript window event.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Important to Note that a &lt;code&gt;CustomEvent&lt;/code&gt; is different from a regular JS &lt;code&gt;Event&lt;/code&gt;. Check &lt;a href="https://stackoverflow.com/a/40795249/3113599" rel="noopener noreferrer"&gt;this&lt;/a&gt; Stackoverflow answer for details.&lt;/p&gt;
&lt;/blockquote&gt;

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

</description>
      <category>alpinejs</category>
      <category>javascript</category>
      <category>googlemaps</category>
    </item>
    <item>
      <title>What, why and how of PHP Composer</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Thu, 14 Jun 2018 14:18:30 +0000</pubDate>
      <link>https://dev.to/gauravmak/what-why-and-how-of-php-composer-21nc</link>
      <guid>https://dev.to/gauravmak/what-why-and-how-of-php-composer-21nc</guid>
      <description>&lt;h3&gt;
  
  
  Let's demystify the package manager Laravel and other frameworks use
&lt;/h3&gt;

&lt;p&gt;Since developers have realized the power and benefits of the DRY approach, lots of frameworks and libraries have been crafted privately and open-source.&lt;/p&gt;

&lt;p&gt;If you're someone like me (myself 2 years ago to be precise), you might say - "Why all these new frameworks are not allowing a direct .zip download? Why do I have to install (and learn) this new Composer thing just to download a framework?"&lt;/p&gt;

&lt;p&gt;Back in the days when I was using &lt;a href="https://codeigniter.com/" rel="noopener noreferrer"&gt;Codeigniter&lt;/a&gt; and &lt;a href="https://cakephp.org/" rel="noopener noreferrer"&gt;CakePHP&lt;/a&gt; 2, I would just download .zip file, extract it in my project directory and start developing. So neat, right? Read on.&lt;/p&gt;

&lt;p&gt;Then, I witnessed new version CakePHP 3 in 2015 (so unlucky I didn't try Laravel that time). It was forcing me to use composer to download the framework and I was very new to it. I was complaining, like &lt;a href="https://stackoverflow.com/q/30412844/3113599" rel="noopener noreferrer"&gt;others&lt;/a&gt;, until I realised how much time and headaches it is going to save for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it Composer?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Composer is a dependency manager and autoloading expert for PHP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you heard about or used &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;? (or yarn) Or if you're a Rubyist, Bundler must not be new to you. &lt;a href="https://getcomposer.org/" rel="noopener noreferrer"&gt;Composer&lt;/a&gt; provides similar functionality for the PHP world. It used to be PEAR (PHP Extension and Application Repository) in early days.&lt;/p&gt;

&lt;p&gt;One important thing to note here is that the open-source packages generally recide on &lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt; and composer downloads the dependencies from there, unless you specify other location. Packagist, in turn, keep and updates the code from Git/Svn repositories. And you can also use private repository with composer by using Private packagist or hosting them yourself.&lt;/p&gt;

&lt;p&gt;I hate theory. Let's have some practical talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pains that Composer fixes
&lt;/h2&gt;

&lt;p&gt;Following are some of pains that Composer has relieved:&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Management
&lt;/h3&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%2Fi%2Fhji5jgwp0cexdgv5p1e7.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%2Fi%2Fhji5jgwp0cexdgv5p1e7.png" alt="Dependency Management" width="188" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you are working on a new project using a framework, you depend on it's updates. As they release new versions with bug fixes and new features, you should keep the framework updated for security, performance, and other reasons.&lt;/p&gt;

&lt;p&gt;But, it's a pain to manually download it everytime, replace the existing files and test things again. It takes time. And that is why there are so many old codebases relying on the versions of frameworks that are no longer supported. Working on legacy projects is something that all of us try to avoid, isn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Project directory size
&lt;/h3&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%2Fi%2F9q0pj4ofo41xtfqw31v8.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%2Fi%2F9q0pj4ofo41xtfqw31v8.png" alt="Project directory size" width="206" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pre-composer days, the size of the project directory used to be very big. We would carry all the libraries that our project depends on and pass around the project either in USB sticks or pollute the VCS (git) history.&lt;/p&gt;

&lt;p&gt;Enter Composer - Size reduces to less than 20%? We can get away without keeping the dependencies in the project (.gitignore) and avoid version mismatches at the same time thanks to &lt;code&gt;composer.lock&lt;/code&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sad fact - Codeigniter 3 still uses the traditional download system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hours of debugging
&lt;/h3&gt;

&lt;p&gt;The libraries or frameworks that your project uses depend on some other libraries (and the chain continues...). Possibly, the framework is using version X of a library while another library is using version Y of the same library.&lt;/p&gt;

&lt;p&gt;You have been getting errors due to some clash or incompatibilty and have to put a lot of time to get to the base of the issue. No more - composer keeps only one copy of a library with a suitable version or denies the installation request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Autoloading
&lt;/h3&gt;

&lt;p&gt;Remember that long list &lt;code&gt;require&lt;/code&gt; statements? As the project grows in size, so does the number of files we need to include in each of the file. PHP autoloading came to the rescue but still it was &lt;a href="https://www.sitepoint.com/autoloading-and-the-psr-0-standard/" rel="noopener noreferrer"&gt;comparatively hard&lt;/a&gt; to setup and maintain as dependencies grow. Less discussed powerful feature of Composer is Autoloading. It supports PSR-0, &lt;a href="https://www.php-fig.org/psr/psr-4/" rel="noopener noreferrer"&gt;PSR-4&lt;/a&gt;, class mapping as well as files autoloading. We need to require just one file and we're done. Play with straightforward namespaces and enjoy the development time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Less known fact - Composer provides three different levels of &lt;a href="https://getcomposer.org/doc/articles/autoloader-optimization.md" rel="noopener noreferrer"&gt;autoloader optimisation&lt;/a&gt; for your different level of needs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lengthy Installation procedures
&lt;/h3&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%2Fi%2Ff0nph5equt1mjrcf4pu4.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%2Fi%2Ff0nph5equt1mjrcf4pu4.png" alt="Lengthy Installation procedures" width="300" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Often times, one or more steps need to be followed after downloading a library for setup and installation. Package maintainers had to write detailed installation procedures in the documentation and still answer support queries when users won't follow them and then complain about errors. &lt;a href="https://getcomposer.org/doc/articles/scripts.md" rel="noopener noreferrer"&gt;Composer scripts&lt;/a&gt; are a boon for them.&lt;/p&gt;

&lt;p&gt;One can easily code the steps that can be automated and run as a script during various stages of the package download. For example, Laravel uses composer scripts to create an &lt;code&gt;.env&lt;/code&gt; file, create an application key, and perform &lt;a href="https://medium.com/@taylorotwell/package-auto-discovery-in-laravel-5-5-ea9e3ab20518" rel="noopener noreferrer"&gt;automatic discovery&lt;/a&gt; of the packages.&lt;/p&gt;

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

&lt;p&gt;The code of your library/package may support only latest PHP versions or depend on specific PHP extensions. And you can inform Composer about this resulting in prevention of package downloads on the systems that don't meet the requirements. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"require": {
    "php": "^7.1.3",
    "ext-mbstring": "*",
    "ext-openssl": "*",
    ...
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this to your &lt;code&gt;composer.json&lt;/code&gt; and composer will throw an error when the systems with PHP less than v7.1.3 or without mbstring and openssl extension try to download the package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintaining a library/package
&lt;/h3&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%2Fi%2F8dhurgoixvmwntcte225.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%2Fi%2F8dhurgoixvmwntcte225.png" alt="Maintaining a library package" width="204" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Package maintainers had to either maintain different directories for each version of the package or release new versions through GitHub everytime there was an important update. Thanks to the graceful integration of Composer with VCS tags and branches, one just needs to add a tag to the commit and push. The rest is taken care of.&lt;/p&gt;

&lt;p&gt;Composer highly recommends &lt;a href="https://semver.org/spec/v2.0.0.html" rel="noopener noreferrer"&gt;Semantic Versioning&lt;/a&gt; and following that, package maintainers can keep focus on actual development without worrying about the distribution.&lt;/p&gt;

&lt;p&gt;Marvellous. I do not have complains any more and am ready to jump in. What next?&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuts and bolts of Composer
&lt;/h2&gt;

&lt;p&gt;Now that we have an idea about what and why of the Composer. Let's jump into the how part:&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;The installation instructions on the composer documentation are pretty clear and I think my best job is to &lt;a href="https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx" rel="noopener noreferrer"&gt;link you there&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consumption
&lt;/h3&gt;

&lt;p&gt;If you want to build a project using Laravel, you need to install it using composer. Though &lt;a href="https://laracasts.com/discuss/channels/laravel/installing-laravel-wihout-composer" rel="noopener noreferrer"&gt;some people&lt;/a&gt; want to go with the traditional way, it is highly discouraged.&lt;/p&gt;

&lt;p&gt;Laravel itself uses lots of useful open-source package like PHPUnit, Monolog, &lt;a href="http://carbon.nesbot.com/docs/" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;, etc. Those dependencies are also managed by composer. You should learn about version management to avoid potential issues.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fun Fact - Composer installs dependencies in the &lt;code&gt;vendor&lt;/code&gt; directory by default but it also supports &lt;a href="https://getcomposer.org/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md" rel="noopener noreferrer"&gt;custom installers&lt;/a&gt; for various package types that can install dependecicies in other directories.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Version management
&lt;/h3&gt;

&lt;p&gt;Understanding how composer downloads the libraries based on the version constraints specified in your &lt;code&gt;composer.json&lt;/code&gt; file will help you a long way. I recommend you to go through the &lt;a href="https://getcomposer.org/doc/articles/versions.md" rel="noopener noreferrer"&gt;original documentation&lt;/a&gt; article at least once.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did you know? - You can require a package by its version, branch or&lt;br&gt;
even by a specific commit SHA (not recommended).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Personally, my suggestion is to use Caret Version Range (^) for the packages which use Semantic versioning and Wildcard Version Range (.*) for others as they are easy to grasp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding composer.lock file
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;composer.json&lt;/code&gt; is managed automatically when you use the &lt;code&gt;create-project&lt;/code&gt; command or when you directly require a package from the terminal. &lt;code&gt;composer.lock&lt;/code&gt; is something you should be aware of.&lt;/p&gt;

&lt;p&gt;First of all, you &lt;a href="https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control" rel="noopener noreferrer"&gt;should commit&lt;/a&gt; your composer.lock file to make sure that everyone of your team members use the same copy of the dependencies while working on a common project. How does that happen?&lt;/p&gt;

&lt;p&gt;Whenever you run &lt;code&gt;composer install&lt;/code&gt;, Composer actually checks for the existence of the composer.lock file. If it is present, it installs all the dependencies as per the lock file which contains exact version numbers and SHAs to be used. If lock file is not present, Composer simply reads the &lt;code&gt;composer.json&lt;/code&gt; file, installs the dependencies and creates the &lt;code&gt;composer.lock&lt;/code&gt; file. Next time you run the install command on server or some other computer, lock file is used to give you the exact same copy.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;code&gt;composer update&lt;/code&gt; command looks at the &lt;code&gt;composer.json&lt;/code&gt; file directly, installs the new versions of the dependencies, if available, as per the version contstraints and updates the lock file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slowness of Composer
&lt;/h3&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%2Fi%2F3m5tzwvuq1vd2rahdn3h.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%2Fi%2F3m5tzwvuq1vd2rahdn3h.png" alt="Slowness of Composer" width="285" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have experienced slow installs and updates by composer. Unknown about what's going on in the background, I would just keep staring at the screen as I wait for it to complete before I can take my next step.&lt;/p&gt;

&lt;p&gt;If you're facing the same issue, I suggest you to append the composer command with &lt;code&gt;--profile&lt;/code&gt; and &lt;code&gt;-vv&lt;/code&gt; or even &lt;code&gt;-vvv&lt;/code&gt; to have more information about background processing. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer install -vv --profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you cannot find any specific issue from the output, you can also try &lt;a href="https://github.com/hirak/prestissimo" rel="noopener noreferrer"&gt;this package&lt;/a&gt; to enable parallel downloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Package development
&lt;/h3&gt;

&lt;p&gt;If are just starting out building your first package/library, there is a very useful tip to make the development easy and comfortable.&lt;/p&gt;

&lt;p&gt;Most of the times, the package/library needs to be tested against an actual project during development and for that - maintainer may need to keep the package inside the actual project to avoid unnecessary multiple releases until he's done.&lt;/p&gt;

&lt;p&gt;Composer &lt;a href="https://getcomposer.org/doc/05-repositories.md#path" rel="noopener noreferrer"&gt;Path repositories&lt;/a&gt; can save yourself from that trap. It will Symlink or Mirror the repo in the project and you can keep the code bases separate and manage and switch them easily.&lt;/p&gt;

&lt;p&gt;Laravel super artisan Caleb Porzio even &lt;a href="http://calebporzio.com/bash-alias-composer-link-use-local-folders-as-composer-dependancies/" rel="noopener noreferrer"&gt;added a bash alias&lt;/a&gt; to use this feature with a single command.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick tip - If your package contains a command line script which you would like to pass along to the users, consider using &lt;a href="https://getcomposer.org/doc/articles/vendor-binaries.md" rel="noopener noreferrer"&gt;vendor binaries&lt;/a&gt;. PHPUnit uses it to quickly let you fire &lt;code&gt;vendor/bin/phpunit&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Branch Aliasis
&lt;/h3&gt;

&lt;p&gt;Once your package/library is already being used by multiple projects, you should also consider adding branch aliasis to make developers' life a bit easier. &lt;a href="https://getcomposer.org/doc/articles/aliases.md" rel="noopener noreferrer"&gt;This article&lt;/a&gt; explains the reason behind it very well and also specifies how to do it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Advanced level developers - Composer allows you to alter or expand it's functionality by using &lt;a href="https://getcomposer.org/doc/articles/plugins.md" rel="noopener noreferrer"&gt;composer-plugins&lt;/a&gt;. You can perform actions when your package is loaded and when certain events are fired.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final notes
&lt;/h2&gt;

&lt;p&gt;This was a bit longer one. We covered quick history about dependency management, learned what Composer is, discussed about the pains that it fixes and then went through some useful points and tips around composer for the new developers and package maintainers.&lt;/p&gt;

&lt;p&gt;That is pretty much what I had to say. If you've reached here all the way from the top reading each line, thank you. I think our thinking style matches. Say hi in the comment section below.&lt;/p&gt;

&lt;p&gt;If you have any questions, feel free to post your comment, I would try my best to solve your queries.&lt;/p&gt;

&lt;p&gt;And If you think this can help other developers in your online network, I’d be happy to see you &lt;a href="https://twitter.com/intent/tweet?text=%F0%9F%91%A8%E2%80%8D%F0%9F%92%BB%20What%2C%20why%20and%20how%20of%20PHP%20Composer%20%F0%9F%95%B8%EF%B8%8F&amp;amp;url=https://dev.to/gauravmak/what-why-and-how-of-php-composer-21nc&amp;amp;via=gauravmakhecha&amp;amp;related=laravelphp&amp;amp;hashtags=laravel"&gt;sharing&lt;/a&gt; this with them. Thanks.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>composer</category>
    </item>
    <item>
      <title>Step by step guide to Laravel package development</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Fri, 25 May 2018 13:20:55 +0000</pubDate>
      <link>https://dev.to/gauravmak/step-by-step-guide-to-laravel-package-development-4nj1</link>
      <guid>https://dev.to/gauravmak/step-by-step-guide-to-laravel-package-development-4nj1</guid>
      <description>&lt;p&gt;Are you curious how open-source Laravel packages are developed from scratch? Or are you unsure whether any specific functionality makes a good use case to be a Laravel package?&lt;/p&gt;

&lt;p&gt;Let’s talk about these and other related questions today.&lt;/p&gt;

&lt;p&gt;We all are fans of Laravel and its ecosystem for its simplicity and extensibility. Packages have been playing a major role in moving it forward. Especially official packages by Laravel,  &lt;a href="https://spatie.be/en/opensource" rel="noopener noreferrer"&gt;Spatie&lt;/a&gt;  ,  &lt;a href="https://github.com/barryvdh/" rel="noopener noreferrer"&gt;Barry vd.&lt;/a&gt; , and others have made our lives and code better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you should build a Laravel Package
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Better coding skills&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open-source is magical. Putting your code out into the public makes you a bit vulnerable at the beginning but brings out the best of you. The fear of doing something wrong prevents every bit of you from doing the  &lt;code&gt;git push origin master&lt;/code&gt;  but it’s always worth it. Laracasts’ series on  &lt;a href="https://laracasts.com/series/how-to-manage-an-open-source-project" rel="noopener noreferrer"&gt;open source project management&lt;/a&gt; can help a lot if you’re not well-versed with GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More (and better) work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will build you brand leading to more work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Talk is cheap. Show me the code." - Linus Torvalds (creator of Linux and Git)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As developers and clients see your code and benefit from it, you will get more recognition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Save time&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You will save yourself considerable amount of time when you convert a piece of code, that you are using in more than one projects, into a package. “DRY” approach isn’t a new thing. We know its benefits.&lt;/p&gt;

&lt;p&gt;In short, open-source package development makes your developer life better.&lt;/p&gt;

&lt;p&gt;Now that we have a better idea about the need to go ahead with package development, let’s make one together now.&lt;/p&gt;

&lt;p&gt;On a side note, contributing to an existing solution is also a great way to start if there is already an open-source package/library of your choice.&lt;/p&gt;

&lt;h4&gt;
  
  
  A new Laravel package from scratch
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Note:&lt;/code&gt;  I had said we will be building a real package. While thinking about an example, the only good option I could come up with was one of my own packages -  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer" rel="noopener noreferrer"&gt;Laravel Log Enhancer&lt;/a&gt;. It is short enough to cover quickly as well as plays with important parts of package development to learn the basics properly.&lt;/p&gt;

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

&lt;p&gt;If you haven’t created any Laravel package before, I insist you to do this with me.  &lt;em&gt;It’ll be fun&lt;/em&gt;. Even if you make the same package, you’ll have more confidence and will be inspired to make changes or create a new one instantly. All the steps are undoable - you’ve nothing to lose. And true learning is all about doing the things practically. Our requirements are basic. If you’re already running any Laravel app locally, you’ve it all.&lt;/p&gt;

&lt;p&gt;Let’s start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. New package directory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a directory with a name of the package. I will call it  &lt;code&gt;laravel-log-enhancer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir laravel-log-enhancer &amp;amp;&amp;amp; cd laravel-log-enhancer 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Love for git&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initialize a git repository. We’ll need GitHub repo to put the package online.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. composer.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every package starts with a  &lt;code&gt;composer.json&lt;/code&gt;  file. Let’s create it. The easiest way to create it is to fire the  &lt;code&gt;init&lt;/code&gt;  command.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Or you can just copy it from  &lt;a href="https://gist.github.com/gauravmak/04badd41d58d8f27648532e93876a634" rel="noopener noreferrer"&gt;this stub&lt;/a&gt; and make changes accordingly.&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%2Fi%2Ft4kxstetmqwseoh7rkcf.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%2Fi%2Ft4kxstetmqwseoh7rkcf.png" alt="Package Composer json file" width="594" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Commit the change. Not compulsory but we will do it after each unique step as a good habit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Namespace and autoloading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We will put the main code of our package in  &lt;code&gt;src&lt;/code&gt;  directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir src &amp;amp;&amp;amp; cd src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By the way, just like Laravel web app development, there are no hard rules about directory structure here but a helpful convention to follow.&lt;/p&gt;

&lt;p&gt;We will update our  &lt;code&gt;composer.json&lt;/code&gt;  file for 2 important things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When a Laravel project uses our package, we can inform it about the location of the files of the package to be loaded by putting the path in PSR-4 autoloading part of  &lt;code&gt;composer.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  To make the installation easy for the developer, we will put the location of the service provider, that should be automatically detected by Laravel, in  &lt;code&gt;extra&lt;/code&gt;  section of the file.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"autoload": {
    "psr-4": {
        "Freshbitsweb\\LaravelLogEnhancer\\": "src/"
    }
},
"extra": {
    "laravel": {
        "providers": [
            "Freshbitsweb\\LaravelLogEnhancer\\LaravelLogEnhancerServiceProvider"
        ]
    }
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By  &lt;em&gt;autoload&lt;/em&gt;, the parent Laravel web app knows about our base namespace i.e.  &lt;code&gt;Freshbitsweb\LaravelLogEnhancer&lt;/code&gt;  and the files location which is the  &lt;code&gt;src&lt;/code&gt;  directory. And Laravel’s awesome  &lt;a href="https://laravel-news.com/package-auto-discovery" rel="noopener noreferrer"&gt;package discovery&lt;/a&gt; feature helps us remove a step from package installation process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The service provider dilemma:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many beginners stuck at this stage. Don’t worry. Let’s try to simplify this. A service provider is a file that can tell the parent Laravel application about various offerings of the package.&lt;/p&gt;

&lt;p&gt;Common belief is that we always need a service provider for a package. That’s not the case. If your package doesn’t need to  &lt;em&gt;autoload&lt;/em&gt;  &lt;a href="https://laravel.com/docs/packages#resources" rel="noopener noreferrer"&gt;any resources&lt;/a&gt; in advance, it can skip the service provider. But in most of the cases, for a package to be useful enough, service provider is required.&lt;/p&gt;

&lt;p&gt;We will use it in our case to load the default configuration options of the package as well as offer an option to export those config options to the parent Laravel web app.&lt;br&gt;
&lt;/p&gt;

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

namespace Freshbitsweb\LaravelLogEnhancer;

use Illuminate\Support\ServiceProvider;

class LaravelLogEnhancerServiceProvider extends ServiceProvider
{
    /**
     * Publishes configuration file.
     *
     * @return  void
     */
    public function boot()
    {
        $this-&amp;gt;publishes([
            __DIR__.'/../config/laravel_log_enhancer.php' =&amp;gt; config_path('laravel_log_enhancer.php'),
        ], 'laravel-log-enhancer-config');
    }

    /**
     * Make config publishment optional by merging the config from the package.
     *
     * @return  void
     */
    public function register()
    {
        $this-&amp;gt;mergeConfigFrom(
            __DIR__.'/../config/laravel_log_enhancer.php',
            'laravel_log_enhancer'
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is quite simple here. In the  &lt;code&gt;boot&lt;/code&gt;  method, we put the code to allow the developer to export the config options by simply writing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish -tag=laravel-log-enhancer-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the  &lt;code&gt;register&lt;/code&gt;  method, we tell the Laravel app to add the config options from our file into the web app config. Commit the update and let’s create our config file next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Config options:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As a part of the convention, we will put our config file in  &lt;code&gt;config&lt;/code&gt;  directory inside root folder next to src directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir config &amp;amp;&amp;amp; cd config &amp;amp;&amp;amp; touch laravel_log_enhancer.php 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put the following code in the file.&lt;br&gt;
&lt;/p&gt;

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

return [
    'log_request_details' =&amp;gt; true,

    'log_input_data' =&amp;gt; true,

    'log_request_headers' =&amp;gt; false,

    'log_session_data' =&amp;gt; true,

    'log_memory_usage' =&amp;gt; false,

    'log_git_data' =&amp;gt; false,

    // You can specify the inputs from the user that should not be logged
    'ignore_input_fields' =&amp;gt; ['password', 'confirm_password'],
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file contains few configuration options just like a regular Laravel config file. Commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Package classes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Final piece of code, for actual enhancement of Laravel logs, is the  &lt;code&gt;LogEnhancer.php&lt;/code&gt;  file. To keep the length of the article digestible, I will directly link you to  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/src/LogEnhancer.php" rel="noopener noreferrer"&gt;the actual class&lt;/a&gt; that you can copy. We also have  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/src/RequestDataProcessor.php" rel="noopener noreferrer"&gt;&lt;code&gt;RequestDataProcessor.php&lt;/code&gt;&lt;/a&gt; in the package. Put both of them in the  &lt;code&gt;src&lt;/code&gt;  directory and you should be good to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Other important files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are few other files that we need to add finally.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/.gitignore" rel="noopener noreferrer"&gt;.gitignore&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/LICENSE" rel="noopener noreferrer"&gt;LICENSE&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/README.md" rel="noopener noreferrer"&gt;README.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;README file needs a special mention here. It is the face of the package. You should be writing detailed installation steps and other notes with proper flow in this file. Go through this  &lt;a href="https://guides.github.com/features/wikis/" rel="noopener noreferrer"&gt;GitHub guide&lt;/a&gt; for more.&lt;/p&gt;

&lt;p&gt;Commit this change and now our package is ready to use.&lt;/p&gt;

&lt;p&gt;What next? It’s time to release it.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to release the package
&lt;/h4&gt;

&lt;p&gt;If you haven’t pushed the package code to GitHub, do it first. If you don’t know how,  &lt;a href="https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/" rel="noopener noreferrer"&gt;this article&lt;/a&gt; can help.&lt;/p&gt;

&lt;p&gt;Then, head over to  &lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt; , create an account or sign in, Click on Submit, specify the GitHub repo URL, … Steps are quite easy and self-explanatory. You should also enable Auto update of the package and consider  &lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;Semantic versioning&lt;/a&gt; and  &lt;a href="https://help.github.com/articles/creating-releases/" rel="noopener noreferrer"&gt;releasing&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feuf25jnzvbbh3hlziyty.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%2Fi%2Feuf25jnzvbbh3hlziyty.png" alt="Packagist screenshot" width="594" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congrats.&lt;/strong&gt;  We’re done. Breath for a few minutes. There’s more.&lt;/p&gt;

&lt;p&gt;Next, there are many other things are not part of the package development but are important for the development lifecycle and maintenance. Let’s go through them quickly.&lt;/p&gt;

&lt;h4&gt;
  
  
  How to use the package locally
&lt;/h4&gt;

&lt;p&gt;We don’t have to push the updates online before testing it locally. Composer repositories path to the rescue.&lt;/p&gt;

&lt;p&gt;Not just the package, we can do it with any repository. Here’s a  &lt;a href="https://tighten.co/blog/testing-laravel-framework-changes-locally-before-submitting-a-pull-request" rel="noopener noreferrer"&gt;great article&lt;/a&gt; explaining the details.&lt;/p&gt;

&lt;p&gt;Let’s do it. Install a fresh Laravel app next to your package directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;laravel new laravel-with-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make changes in it’s  &lt;code&gt;composer.json&lt;/code&gt;  file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"repositories": [
    {
        "type": "path",
        "url": "../laravel-log-enhancer"
    }
],
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the package by firing the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require gauravmak/laravel-log-enhancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete the  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer#installation" rel="noopener noreferrer"&gt;installation steps&lt;/a&gt; and you can use the package now.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;“I find that weeks of coding and testing can save me hours of planning.” -&lt;br&gt;
 Unknown&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They say - do not use a package without tests. They’re right. As the package gets bigger in size and more contributors enter the scene, some random commit can break the code functionality somewhere down the line. And we never want it to happen, right?&lt;/p&gt;

&lt;p&gt;And it’ not hard. All we need to do it to check if the package is doing what it is supposed to do after every change/commit. In this package, we are adding processors to the Monolog handlers so that more data can be logged.&lt;/p&gt;

&lt;p&gt;Unfortunately, as of now, Monolog doesn’t provide a method to fetch the processors of a handler so we are limited but let’s create a base of the testing for this package so that you know how to add tests to your custom package.&lt;/p&gt;

&lt;p&gt;To start, we will add requirements to the  &lt;code&gt;composer.json&lt;/code&gt;  file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"require-dev": {
    "phpunit/phpunit": "^7.0",
    "orchestra/testbench": "~3.6.0"
 },
 "autoload-dev": {
    "psr-4": {
        "Freshbitsweb\\LaravelLogEnhancer\\Test\\": "tests"
    }
 },
 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are basically testing a package which is outside a Laravel app.  &lt;a href="https://github.com/orchestral/testbench" rel="noopener noreferrer"&gt;orchestral/testbench&lt;/a&gt; is a great package which can add the necessary dependencies so that we can test it as if we have all the Laravel goodies.&lt;/p&gt;

&lt;p&gt;I have also added the following files to make the base of testing for our app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/phpunit.xml.dist" rel="noopener noreferrer"&gt;phpunit.xml.dist&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/tests/LogEnhancerTest.php" rel="noopener noreferrer"&gt;LogEnhancerTest.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/freshbitsweb/laravel-log-enhancer/blob/master/tests/TestCase.php" rel="noopener noreferrer"&gt;TestCase.php&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go through the README file of the testbench package for all details about how we can interact with Laravel while testing our package.&lt;/p&gt;

&lt;h4&gt;
  
  
  Integrations
&lt;/h4&gt;

&lt;p&gt;There are so many helpful tools that integrate with GitHub repo and help us maintain the packages/libraries easily.&lt;/p&gt;

&lt;p&gt;I suggest  &lt;a href="https://github.com/marketplace/travis-ci" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt; for testing the package after each update and  &lt;a href="https://github.com/marketplace/styleci" rel="noopener noreferrer"&gt;StyleCI&lt;/a&gt; for maintaing the code style.&lt;/p&gt;

&lt;p&gt;I have integrated StyleCI in the package already. You should also consider  &lt;a href="https://poser.pugx.org/" rel="noopener noreferrer"&gt;adding badges&lt;/a&gt; to the README file.&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%2Fi%2Fkujka3mxmuct6g7x38u2.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%2Fi%2Fkujka3mxmuct6g7x38u2.png" alt="Package Badges" width="624" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Secret sauce of a successful package
&lt;/h4&gt;

&lt;p&gt;You reap the benefits of making the package when more and more developers use it. And for that, there are so many factors starting from the basic idea behind the package to the stability and age of the package (stars).&lt;/p&gt;

&lt;p&gt;If I were to decide on most important point for that, it would be the  &lt;em&gt;developer friendliness&lt;/em&gt;  of the package. Yes, the exact reason why Laravel is popular.&lt;/p&gt;

&lt;p&gt;Try to minimize the installation steps and the code that is required to use the package. Plus, it has to be  &lt;strong&gt;readable enough&lt;/strong&gt;  that it doen’t need to annotated with long comments.&lt;/p&gt;

&lt;p&gt;For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$users = User::with('roles')-&amp;gt;get();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So simple, we know this operation involves join queries and other stuff. Still, you like to write it and read it. Do things on a similar level.&lt;/p&gt;

&lt;h4&gt;
  
  
  Final notes
&lt;/h4&gt;

&lt;p&gt;That’s it for the day. We learned why package development is good for everyone and how to do it step-by-step using a real example. If you have any questions or get stuck anywhere, just add a comment below, I would be happy to help.&lt;/p&gt;

&lt;p&gt;And If you think this can help other Laravel developers in your online network, I’d be happy to see you  &lt;a href="https://twitter.com/intent/tweet?text=%F0%9F%94%A5Checkout%20step%20by%20step%20guide%20to%20Laravel%20package%20development%20%F0%9F%93%A6%20with%20a%20real%20example.&amp;amp;url=https://dev.to/gauravmak/step-by-step-guide-to-laravel-package-development-4nj1&amp;amp;via=gauravmakhecha&amp;amp;related=laravelphp&amp;amp;hashtags=laravel"&gt;sharing&lt;/a&gt; this with them. Thanks.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>packagedevelopment</category>
    </item>
    <item>
      <title>Time-saving habits for programmers</title>
      <dc:creator>Gaurav Makhecha</dc:creator>
      <pubDate>Thu, 26 Apr 2018 14:10:00 +0000</pubDate>
      <link>https://dev.to/gauravmak/time-saving-habits-for-programmers-i37</link>
      <guid>https://dev.to/gauravmak/time-saving-habits-for-programmers-i37</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;"I wish there were more than 24 hours in a day to let me achieve more."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you ever desired to have more time available for  &lt;em&gt;completing your side-projects&lt;/em&gt;  or meeting the deadline, just like me?&lt;/p&gt;

&lt;p&gt;Both of us know there cannot be more than 24 hours a day; the Better choice is to just use the time that we have in the most efficient way.&lt;/p&gt;

&lt;p&gt;There are many habits that help programmers perform better and leverage limited time. There are no shortcuts. It is all about good habits. Once formed, they can save a ton of time for you. Let's cover some of those habits very quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Time tracking earns
&lt;/h3&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%2Fi%2F3vcaj7203pfzricwy0yf.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%2Fi%2F3vcaj7203pfzricwy0yf.png" alt="Time tracking earns" width="500" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do you know how many minutes do you take to complete the X task? And how much of your work time is actually invested in developing stuff? 80%? 70? Way less than you think it is if you’re not tracking time currently. What about your team? How many hours do they code every working day?&lt;/p&gt;

&lt;p&gt;It is very important to measure each of your activities on a day-to-day basis. Only then you can provide estimates for future projects properly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"When work time is tracked, efficiency improves. And when the tracked time is being reported, speed of efficiency improvement doubles."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fruits of this habit are way beyond statistics.&lt;/p&gt;

&lt;p&gt;You can use any of the available  &lt;a href="https://www.entrepreneur.com/article/269991" rel="noopener noreferrer"&gt;time tracking tools&lt;/a&gt; .  &lt;a href="https://toggl.com/" rel="noopener noreferrer"&gt;Toggl&lt;/a&gt;  has served me well for a few years now and I cannot recommend it enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Distraction-free workspace
&lt;/h3&gt;

&lt;p&gt;Every now and then, we read articles on the 21st-century gadgets distracting us every few minutes. The benefit of technology advancements is that we have easy access to an ocean of knowledge now&lt;/p&gt;

&lt;p&gt;But, too many attention seekers in today’s social world are breaking our workflow. Focus is more important than information, talent or intelligence.&lt;/p&gt;

&lt;p&gt;A practical tip would be to keep your phone away while working and turning off all those notifications to improve your focus and concentration. Using good quality headphones or  &lt;a href="https://www.amazon.com/Best-Sellers-Health-Personal-Care-Earplugs/zgbs/hpc/3779871" rel="noopener noreferrer"&gt;ear plugs&lt;/a&gt;  for noise cancellation is a no-brainer&lt;/p&gt;

&lt;p&gt;I have used  &lt;a href="https://francescocirillo.com/pages/pomodoro-technique" rel="noopener noreferrer"&gt;Pomodoro&lt;/a&gt;  technique myself and it has helped me stay focused a lot.  &lt;em&gt;Constraints bring creativity&lt;/em&gt;. Try it. There are many regular practitioners of  &lt;a href="https://gettingthingsdone.com/" rel="noopener noreferrer"&gt;Getting Things Done&lt;/a&gt;  as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Pair Programming
&lt;/h3&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%2Fi%2Fb7egiz77rayo2l7npkez.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%2Fi%2Fb7egiz77rayo2l7npkez.png" alt="Pair Programming" width="500" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have been enjoying the fruits of this habit recently. You might say: "&lt;em&gt;How can the time be saved if 2 people are working on a single task together?&lt;/em&gt;" I had the exact same question before.&lt;/p&gt;

&lt;p&gt;Still, to give it a try, I started coding the system for this site with a teammate and there are more PROs to this method than CONs. We could decide on the system architecture pretty quickly, solve issues faster and the main benefit was that both of us were quite focused.&lt;/p&gt;

&lt;p&gt;Our mind is constantly wandering but when there is someone watching you during the coding sessions, the peer pressure keeps your concentration intact. And that is why live streaming of coding sessions is getting popular as people are seeing the advantages of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Pair programming may not help in all cases. Firstly, both the developers should be on a somewhat similar experience level. Maximum time is saved when the project involves complex logic and updates. I would just say - try and see if it works in your case.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Energy management for good mood
&lt;/h3&gt;

&lt;p&gt;A programmer’s work is completely a mind game. Only a sound mind can effectively achieve desired outcomes. Every one of us experiences flow in work occasionally and wish to have it every time we sit in front of the computer, isn’t it so? And for that, we need to train our minds. It's all about  &lt;em&gt;energy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Every decision you make throughout the day uses energy and brings fatigue. Be a morning person. Most of us have a vibrant mind in the morning time. (I know, few owls!..) Observe your mood timings. When do you perform at a very low level? And when is the peak? Build a great routine around it and energy will flow throughout the day.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Divide and conquer
&lt;/h3&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%2Fi%2Fiw8qe445iyzt6ctaxt2z.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%2Fi%2Fiw8qe445iyzt6ctaxt2z.png" alt="Divide and conquer" width="500" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like we take our meal ‘bite’ wise, our work assignments need to be completed in steps too. Whenever you are about to start a task, the first step would be to break it down into smaller logical pieces and execute them one-by-one. You would assign a specific time to each task using the methods discussed above.&lt;/p&gt;

&lt;p&gt;If not, you would, like I do many times, be staring at the screen, thinking about various future problems and their solutions for a couple of hours. No work is done. Dividing the task into easy-to-digest pieces/sprints saves time.&lt;/p&gt;

&lt;p&gt;And this habit is connected with one very important point -  &lt;code&gt;No Multi-Tasking&lt;/code&gt;. I can’t recommend this enough. There would be thousands of articles throwing light on this single term especially. Doing several tasks at a time is a badge of pride for many of us; it is one of the biggest barriers to higher productivity at the same time. Our mind is designed to do only one task very effectively. You may try both ways and measure the results yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Take a Break, buddy!
&lt;/h3&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%2Fi%2F04s7c7j9iwwnisjjkzl1.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%2Fi%2F04s7c7j9iwwnisjjkzl1.png" alt="Take a Break, buddy" width="500" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have loaded our minds with lots of information and processed so many thoughts, let's talk about breaks. Standing up periodically is required for "office workers" to prevent backaches.&lt;/p&gt;

&lt;p&gt;And just like your body, your mind needs rest as well. As we know, muscles do not grow while one is working out at the gym; They get stronger during the relaxation phase instead. The same is true for the brain. Let it repair and restore the parts after a heavy dose of work. In fact, we often get solutions to our problems during our leisure time.&lt;/p&gt;

&lt;p&gt;This habit can save time in 2 ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;By doing some stretches during a break will lead to a healthy body. And yeah, we add lots of hours to our life span with that&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let me illustrate with an example:&lt;br&gt;&lt;br&gt;
&lt;code&gt;4:40 PM:  You have been trying to troubleshoot a complex bug for 40 mins and still nowhere.&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;4:45 PM:  You decide to take a 5-min break finally to give it a last chance before you have to leave at 5.&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;4:55 PM:  5 minutes after returning from a break, you have solved it. Bingo!&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  7. Practice-clad foundation
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"The only way to learn a new programming language is by writing programs in it."&lt;strong&gt;Dennis Ritchie&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most common advice while learning a new language and probably the least followed one as well. In today’s world, we love  &lt;em&gt;everything to be fast&lt;/em&gt;; Be it cars, computers, or mobiles. At the same time, our learning is becoming rapid day by day.&lt;/p&gt;

&lt;p&gt;We like to just  &lt;em&gt;skim through&lt;/em&gt;  the articles (if you read this, you are not skimming, cheers), documentations and videos when we are learning something new. While this is helpful in a few cases, detailed learning is hardly exercised. Simply put, do  _sample projects_repeatedly when you learn new tools/frameworks to master them.&lt;/p&gt;

&lt;p&gt;At the same time, practice and mistakes go hand in hand. Never let the fear of mistakes stop you from acting. While acquiring knowledge, the more mistakes you make, the quicker you become adept at the respective skills. Mistakes while learning is good.&lt;/p&gt;

&lt;p&gt;A proper foundation of logic and programming lets you complete a project in half the time others take. The 10,000 hours rule does have essence I believe.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Code quality
&lt;/h3&gt;

&lt;p&gt;In programming, there is no right way to do things. Every style is opinionated. You just have to pick one that suits yours and follow it. At the end of the day, the code should be  &lt;code&gt;Readable, Maintainable, Well-tested, and Well-documented&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This will save time in the future. Software is never done. There are constant bug fixes, features additions, and requirements updates. If the code is readable enough, you can make the changes quickly. A maintainable code will be easy to approach while adding new functionalities. A well-tested one will boost your confidence and avoid the worries of domain-level effects during code updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Forget office politics
&lt;/h3&gt;

&lt;p&gt;Finally, this habit is going to take you to higher levels in the long run. We get into the competition with co-workers, unconsciously sometimes. This wastes a lot of time. We throw away more energy while trying to win the game instead of focusing on actual work.&lt;/p&gt;

&lt;p&gt;The other benefit of ‘being’ together is long-term growth. Sharing is caring. When ‘I’ becomes ‘We’, each person of the group excels gradually.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If you want to walk fast, walk alone. But if you want to walk far, walk together."&lt;strong&gt;Ratan Tata&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just like savings, working as a team is hard at first and very fruitful eventually. Try that and you will never regret it.&lt;/p&gt;

&lt;h4&gt;
  
  
  That's it!
&lt;/h4&gt;

&lt;p&gt;These are important points, among others, which can help us achieve our goals. I would appreciate you sharing them with others. You are welcome to share your tips below in the comments section. Thank you.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>tips</category>
      <category>workflow</category>
    </item>
  </channel>
</rss>
