<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Samuel Olaegbe</title>
    <description>The latest articles on Forem by Samuel Olaegbe (@samuelolaegbe).</description>
    <link>https://forem.com/samuelolaegbe</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%2F311331%2F6d4d0d0a-159f-48f4-bda0-ee29bcc3c0fa.jpeg</url>
      <title>Forem: Samuel Olaegbe</title>
      <link>https://forem.com/samuelolaegbe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/samuelolaegbe"/>
    <language>en</language>
    <item>
      <title>How to authenticate your frontend apps with Laravel Sanctum</title>
      <dc:creator>Samuel Olaegbe</dc:creator>
      <pubDate>Mon, 14 Dec 2020 10:54:12 +0000</pubDate>
      <link>https://forem.com/samuelolaegbe/how-to-authenticate-your-frontend-apps-with-laravel-sanctum-5g7b</link>
      <guid>https://forem.com/samuelolaegbe/how-to-authenticate-your-frontend-apps-with-laravel-sanctum-5g7b</guid>
      <description>&lt;h2&gt;
  
  
  Passport or Sanctum?
&lt;/h2&gt;

&lt;p&gt;One popular question I have seen everywhere is people asking: "Should I use Passport or Sanctum to authenticate my API"? I have seen people answer this in various ways, but my answer is: Use Sanctum when you need to create a frontend application to interact with your API. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanctum&lt;/strong&gt; provides authentication for your frontend application without the need for tokens unlike Passport, and that isn't to say Sanctum isn't capable of issuing tokens, you can also issue tokens with abilities (read: scope as used in Oauth) to users to authenticate all requests made to your API.&lt;/p&gt;

&lt;p&gt;The two core functionalities Sanctum provides are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateful authentication&lt;/li&gt;
&lt;li&gt;API Tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I love to use Sanctum when building an API backend with Laravel that will interact with a frontend application as it's simple and straight-forward to use for that purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passport&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Passport is a much more compact tool than Sanctum, with a lot of options for authenticating your users. This is more appropriate when building an application that offers &lt;a href="https://oauth2.thephpleague.com/" rel="noopener noreferrer"&gt;Oauth2&lt;/a&gt; capabilities, to enable your users to connect an external service with your application and also gives you the capability to grant each application scopes and abilities. &lt;/p&gt;

&lt;p&gt;If you want to build an application that needs to issue &lt;a href="https://oauth2.thephpleague.com/" rel="noopener noreferrer"&gt;Oauth2&lt;/a&gt; tokens to external applications that may connect with a tool like &lt;a href="https://laravel.com/docs/8.x/socialite#introduction" rel="noopener noreferrer"&gt;Socialite&lt;/a&gt;, then Passport is definitely the right choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing sanctum in your Laravel application
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://laravel.com/docs/8.x/sanctum" rel="noopener noreferrer"&gt;Laravel docs&lt;/a&gt; provide the information needed to set up Sanctum for your application, but I still got confused about setting it up and deciding what was right for my use case between the API tokens option and SPA Authentication option. So I have written this guide hoping it will help anyone else setting Sanctum for the first time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the &lt;a href="https://laravel.com/docs/8.x/sanctum" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Leave the default options for model name and migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  API Tokens or SPA Authentication
&lt;/h3&gt;

&lt;p&gt;Sanctum provides these two authentication methods to you by default and you do not have to use the two at once. I have put together this shortlist to determine which one is best to use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPA Authentication:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateful authentication without tokens.&lt;/li&gt;
&lt;li&gt;CSRF protection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;API Tokens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Issue tokens to users&lt;/li&gt;
&lt;li&gt;Authenticate users with Bearer Authorization&lt;/li&gt;
&lt;li&gt;Attach &lt;code&gt;abilities&lt;/code&gt; to tokens for access control&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;To use the SPA Authentication, your SPA has to be on the same domain as your Laravel API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The stateful authentication method uses Laravel sessions to authenticate the user and thus eliminating the need for tokens, and I think that is super smart! &lt;/p&gt;

&lt;p&gt;To authenticate with this method, note that you need to use the &lt;code&gt;web&lt;/code&gt; middleware as the Laravel session is only available through this middleware.&lt;/p&gt;

&lt;p&gt;You could write your own custom authentication or use any of &lt;a href="https://laravel.com/docs/8.x/starter-kits" rel="noopener noreferrer"&gt;Laravel starter kits&lt;/a&gt; to authenticate, I love to use &lt;a href="https://laravel.com/docs/8.x/starter-kits#laravel-breeze" rel="noopener noreferrer"&gt;Breeze&lt;/a&gt; and take out the views as this is an API only application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring your 3rd party domains
&lt;/h3&gt;

&lt;p&gt;In order for Sanctum to maintain stateful authentication, you need to configure your application's domain names from &lt;code&gt;config/sanctum.php&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="cm"&gt;/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/&lt;/span&gt;

&lt;span class="s1"&gt;'stateful'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'SANCTUM_STATEFUL_DOMAINS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'localhost,localhost:8000,localhost:8080,::1'&lt;/span&gt;
&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setting notifies Sanctum on which domains it should keep your users logged in using cookie based session authentication. We want our users to remain logged-in on our SPA and also our API.&lt;/p&gt;

&lt;p&gt;While in development, you want to make sure you add the different port names for your Laravel application and your SPA.&lt;/p&gt;

&lt;p&gt;Above we have added &lt;code&gt;localhost:8000&lt;/code&gt; which is same as &lt;code&gt;127.0.0.1:8000&lt;/code&gt; for our Laravel application and we have also added &lt;code&gt;localhost:8080&lt;/code&gt; which the URL of our SPA which is also running locally. Of course, you can change this to whatever the URL of your SPA is. I am using a Vue CLI app and the default URL is &lt;code&gt;localhost:8080&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Note that you have to update these settings in our environment variables once our app is deployed. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You should clear your application cache with &lt;code&gt;php artisan config:cache&lt;/code&gt; after changing your config files to make sure the new changes are working.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Add the Sanctum middleware
&lt;/h3&gt;

&lt;p&gt;Follow the &lt;a href="https://laravel.com/docs/8.x/sanctum#sanctum-middleware" rel="noopener noreferrer"&gt;docs&lt;/a&gt; to add the Sanctum middleware.&lt;/p&gt;

&lt;h3&gt;
  
  
  CORS
&lt;/h3&gt;

&lt;p&gt;If your SPA is on a different URL like we have in this tutorial, you will come across cross-site resource sharing errors (cors), but do not fret, I will show you how to overcome those. First you should make sure the API paths you will be accessing via the SPA are listed in the &lt;code&gt;paths&lt;/code&gt; key of the &lt;code&gt;config/cors.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/&lt;/span&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paths&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api/*&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;sanctum/csrf-cookie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="c1"&gt;//define other custom paths&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, we have defined the paths we will be accessing on the API. The first is the &lt;code&gt;/api/*&lt;/code&gt; path which will be handling all requests to our API routes in the &lt;code&gt;routes/api.php&lt;/code&gt; file. We have also defined the &lt;code&gt;sanctum/csrf-cookie&lt;/code&gt; path which will set the headers for our application to use in subsequent requests to the backend. More details on this can be found in the &lt;strong&gt;Authentication&lt;/strong&gt; section.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TIP: You may configure the prefix for the routes defined in &lt;code&gt;routes/api.php&lt;/code&gt; from &lt;code&gt;App\Providers\RouteServiceProvider.php&lt;/code&gt;, or even set a new prefix for a new file path in the routes folder.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While testing, you should set your &lt;code&gt;domains&lt;/code&gt; key in &lt;code&gt;config/sessions.php&lt;/code&gt; to &lt;code&gt;[localhost](http://localhost)&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="s1"&gt;'domain'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the frontend, you should use a library like &lt;a href="https://www.npmjs.com/package/axios" rel="noopener noreferrer"&gt;Axios&lt;/a&gt; with Vue or React which already helps you set your headers based on the response from the server during the initial authentication request as we will see below. &lt;/p&gt;

&lt;p&gt;Further, you should set the &lt;code&gt;withCredentials&lt;/code&gt; option of axios to true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To enable Laravel transform XHTTP (or Ajax) responses to JSON instead of the regular redirect or view responses, you should set the &lt;code&gt;Accept&lt;/code&gt; header to &lt;code&gt;application/json&lt;/code&gt; when making requests.&lt;/p&gt;

&lt;p&gt;In a Vue CLI app, this can be done from the &lt;code&gt;main.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productionTip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Accept&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Requested-With&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;withCredentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;p&gt;The method of authentication Sanctum uses is similar to the regular authentication method in Laravel. The only difference is that you have to first make a post request to &lt;code&gt;sanctum/csrf-token&lt;/code&gt; from your frontend application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
            &lt;span class="c1"&gt;//initial request to set Laravel authentication cookies&lt;/span&gt;
      &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8000/sanctum/csrf-cookie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;//make a request to /login&lt;/span&gt;
        &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8000/login&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;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;olaegbesamuel@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strong-password&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;//do anything with returned response&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get authenticated user from a protected route
&lt;/h3&gt;

&lt;p&gt;To protect a route with Sanctum, you need to apply the &lt;code&gt;auth:sanctum&lt;/code&gt; middleware to the route definition:&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;//api.php&lt;/span&gt;
&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'auth:sanctum'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/me'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If Sanctum was set up correctly you should get the authenticated user back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Samuel Olaegbe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"olaegbesamuel@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"email_verified_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2020-12-12T23:19:04.000000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2020-12-12T23:19:04.000000Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;While building a Laravel powered API, this is one of the problems we are faced with and I had to do a lot of research to get this working solution that has worked for me and thought to share it here. This post should be a guide on best practices on how to authenticate your first-party SPA with Sanctum and would be updated regularly. &lt;/p&gt;

&lt;p&gt;Taylor promised some additional documentation on how to do this well:&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1334587723269763074-100" src="https://platform.twitter.com/embed/Tweet.html?id=1334587723269763074"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1334587723269763074-100');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1334587723269763074&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Let me know if you have any questions or additions and I will be happy to discuss them!&lt;/p&gt;

&lt;p&gt;PS: Subscribe to my blog so you could receive an email each time I publish content.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to speed up database performance with indexes</title>
      <dc:creator>Samuel Olaegbe</dc:creator>
      <pubDate>Mon, 12 Oct 2020 08:15:52 +0000</pubDate>
      <link>https://forem.com/samuelolaegbe/optimizing-database-queries-in-large-applications-7ah</link>
      <guid>https://forem.com/samuelolaegbe/optimizing-database-queries-in-large-applications-7ah</guid>
      <description>&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;In this article we will take a look at how to optimize database queries in a Laravel or PHP application with a MySQL database. At &lt;a href="https://expenseng.com"&gt;ExpenseNG&lt;/a&gt;, our database keeps growing quickly as we record more government expenses from the Nigerian Open Treasury website. For an app that started at a bootcamp, we weren't prepared for the impact a growing database would have on the website. &lt;/p&gt;

&lt;p&gt;With these amount of records we had the responsibility of visualizing these data on our website in the way that has most meaningful impact and passed across the right information, which is &lt;strong&gt;Where is the government spending most money?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you visit the &lt;a href="https://expenseng.com/contractors"&gt;contractors&lt;/a&gt; page on ExpenseNG, you will see the list of everyone that has received money from the government sorted by the contractor who got the most money in the last completed month and you can also see the total amount they got for that month. The data looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Contractor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Amount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Received:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Month&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Ended:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Challenge
&lt;/h3&gt;

&lt;p&gt;Now that we know what the data we need looks like, let's take a look at what it takes to retrieve this data from the database.&lt;/p&gt;

&lt;p&gt;Two tables are involved in this operation and they are the &lt;code&gt;contractors&lt;/code&gt; and &lt;code&gt;payments&lt;/code&gt; table. The contractors table holds the records of all everyone that has received money from the government and the payments table holds the records of every payment ever made and a reference to their recipients.&lt;/p&gt;

&lt;p&gt;The tables schema looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;payments:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;amount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(double)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(DATE)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;recipient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(string)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;contractors:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(string)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To sort the results from getting all the records from the contractors table by the total amount received by a contractor from the past month, that already sounds like a query involving two tables and we can achieve that with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&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="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; 
&lt;span class="n"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt; 
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the query above, we have a sub-select statement which helps us to calculate the total money received by all recipients and we can use the result from that sub-query to create a new column in our query which we can now use to sort our final result. The new column created by this sub-query is given an alias of &lt;code&gt;total&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The query above doesn't include the logic for fetching only results from the month ended, so we will modify the query further below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&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="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; 
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="k"&gt;BETWEEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; 
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt; 
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above query, we have added a new constraint to the sub-query which is &lt;code&gt;BETWEEN&lt;/code&gt;. As you know this allows us to select only results that start from the first value and end on the second value.&lt;/p&gt;

&lt;h3&gt;
  
  
  New problem
&lt;/h3&gt;

&lt;p&gt;The query above works fine when you have a few records in your database, but when working with a database with thousands of records this can easily result in the query taking several minutes to execute or even resulting in a request timeout error on the server as the server doesn't receive a response for too long.&lt;/p&gt;

&lt;p&gt;We can easily solve this problem by adding an index to the columns that are pivotal to our query, from the above query the columns we should add an index to are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;contractors.name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;payments.recipient&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;payments.date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;payments.amout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The query to add an index to our columns will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;name_index&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or if you are using Laravel migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;//database/migrations/2020_09_20_102101_add_index_to_payments_table.php&lt;/span&gt;
&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'payments'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'recipient'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'amount'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can reduce our query execution time greatly by adding indexes. On ExpenseNG, our queries went from timing out after several minutes to a about 0.02 seconds with a pagination of 20 results per page.&lt;/p&gt;

&lt;p&gt;We can further improve our query execution time by only selecting the columns that we need, we will change this line to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contractors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt; 
&lt;span class="p"&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Laravel's Eloquent
&lt;/h3&gt;

&lt;p&gt;We can achieve the same queries as we did above in Eloquent by using the &lt;code&gt;addSelect&lt;/code&gt; method to create a sub-query to our original query:&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;Contractor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;select&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;'shortname'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSelect&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'total'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;selectRaw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SUM(amount)'&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;whereColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'recipient'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'contractors.name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;whereBetween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$monthStart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$monthEnd&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'total'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'desc'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&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 are using Eloquent's advanced sub-queries which gives us a nice and comprehensive API to retrieve results from our model. If we wanted, we could lazy load our &lt;code&gt;Contractor&lt;/code&gt; model relationships by chaining the the select method with &lt;code&gt;with('payments')-&amp;gt;paginate(20)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And that is how you optimize database queries on a large MySQL database.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adding an index to a table makes &lt;code&gt;UPDATE&lt;/code&gt; queries run for a longer time, so you should not use them on tables that will get update frequently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dzone.com/articles/how-to-optimize-mysql-queries-for-speed-and-perfor"&gt;https://dzone.com/articles/how-to-optimize-mysql-queries-for-speed-and-perfor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/8.x/migrations#indexes"&gt;https://laravel.com/docs/8.x/migrations#indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/8.x/eloquent#advanced-subqueries"&gt;https://laravel.com/docs/8.x/eloquent#advanced-subqueries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mysql</category>
      <category>php</category>
      <category>database</category>
      <category>laravel</category>
    </item>
    <item>
      <title>Static analysis with Phpstan</title>
      <dc:creator>Samuel Olaegbe</dc:creator>
      <pubDate>Mon, 05 Oct 2020 11:23:05 +0000</pubDate>
      <link>https://forem.com/samuelolaegbe/static-analysis-with-phpstan-1jo5</link>
      <guid>https://forem.com/samuelolaegbe/static-analysis-with-phpstan-1jo5</guid>
      <description>&lt;p&gt;Testing your code is one way to ensure that you have a high quality codebase, which is one way to ensure the maintainability of your projects and also a way to ensure you don't ship broken features in your product. CI tools like &lt;a href="https://travis-ci.org/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt; help you to test your code each time you push to source control.&lt;/p&gt;

&lt;p&gt;Static analysis is the method of testing your code for basic logical, runtime or typographical exceptions without actually executing the code. &lt;/p&gt;

&lt;p&gt;As you must have guessed, static analysis of your codebase happens fast since the code doesn't actually get executed but scanned for common errors like having a method that doesn't return the expected date type.&lt;/p&gt;

&lt;h2&gt;
  
  
  How static analysis works
&lt;/h2&gt;

&lt;p&gt;Static analysis as the name implies, actually doesn't need to execute your code before catching bugs in them. Statically typed languages like Dart or Java already have this functionality built into their compilers. Since they always define the &lt;code&gt;types&lt;/code&gt; of their constructs the compiler won't run when there is a typo or an incorrect type for a method or variable. Before the advent of static analysis and tools like PHPStan, developers spend a lot of time debugging their PHP code looking for errors because PHP's execution is line by line and so it only throws an error when it gets to the line containing the error. And may sometimes continue execution after encountering the error, depending on the type of error encountered.&lt;/p&gt;

&lt;p&gt;PHPStan checks for a couple of language constructs such as use of &lt;code&gt;instanceof&lt;/code&gt;, &lt;code&gt;try-catch&lt;/code&gt; blocks, &lt;code&gt;typehints&lt;/code&gt;, number of arguments passed to a function, accessibility of called methods and variables, &lt;a href="https://phpstan.org/blog/find-bugs-in-your-code-without-writing-tests#what-it-currently-checks-for%3F" rel="noopener noreferrer"&gt;and many more&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  PHPStan: Static analysis in your favourite language
&lt;/h2&gt;

&lt;p&gt;Recently, &lt;a href="https://phpstan.org/blog/introducing-phpstan-pro" rel="noopener noreferrer"&gt;PHPStan Pro&lt;/a&gt; was announced by the creators of PHPStan and that is already looking very promising with continuous watch mode (hot-reloading in PHP?), a Web UI and an interactive fixer! The good news is you get to save a ton of time and keystrokes by finding errors sooner and PHPStan can suggest a fix for you and everyone is happier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using PHPStan in your projects
&lt;/h3&gt;

&lt;p&gt;Below we will go over steps to use PHPStan in our projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up your environment
&lt;/h3&gt;

&lt;p&gt;You can use PHPStan in any PHP project of your choice, for the purpose of this tutorial I have created a skeleton PHP library that I will be using. My &lt;code&gt;composer.json&lt;/code&gt; file looks like this before installing &lt;code&gt;phpstan&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%2Fgoodhands.github.io%2Fassets%2Fstatic%2Fphpstan.cf9e763.bf901c8f3a252f06323e7c18cb51e108.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%2Fgoodhands.github.io%2Fassets%2Fstatic%2Fphpstan.cf9e763.bf901c8f3a252f06323e7c18cb51e108.png" alt="My composer.json"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A screenshot of my composer.json setup&lt;/p&gt;

&lt;p&gt;Installing PHPStan as a dev dependency&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;composer&lt;/span&gt; &lt;span class="k"&gt;require&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dev&lt;/span&gt; &lt;span class="n"&gt;phpstan&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;phpstan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;We are installing &lt;code&gt;phpstan&lt;/code&gt; as a dev dependency with composer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now you are ready to run your first analysis, copy and paste the code below in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;phpstan&lt;/span&gt; &lt;span class="n"&gt;analyse&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the content of your &lt;code&gt;src&lt;/code&gt; directory you may get some errors after running this command and that is totally fine as we will look at how to configure PHPStan to our taste soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  phpstan Command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;analyse&lt;/code&gt; keyword is what tells &lt;code&gt;phpstan&lt;/code&gt; to analyse your codebase, and the 3rd argument in the command is the path to the code you want to analyse. Here I have used &lt;code&gt;src&lt;/code&gt; as that is where the code I have written lives, I do not need to analyse my vendor folder or other temporary folders. However if you are writing tests then it's a good idea to analyse your &lt;code&gt;tests&lt;/code&gt; directory as well. PHPStan has some &lt;a href="https://phpstan.org/user-guide/extension-library" rel="noopener noreferrer"&gt;extensions&lt;/a&gt; for popular testing libraries like PHPUnit, Behat and mock frameworks like Mockery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;PHPStan makes use of the &lt;a href="https://ne-on.org/" rel="noopener noreferrer"&gt;&lt;code&gt;neon&lt;/code&gt;&lt;/a&gt; file format for its configuration, ideally you will have a &lt;code&gt;phpstan.neon&lt;/code&gt; at the root of your project folder. Whenever you run the &lt;code&gt;phpstan analyse&lt;/code&gt; command, it will look for &lt;code&gt;phpstan.neon&lt;/code&gt; at the root and use it as configuration to analyse your code. If it doesn't find the configuration file at the root of your project, PHPStan will also check for &lt;code&gt;phpstan.neon.dist&lt;/code&gt; and if that doesn't exist as well, it will run with the default configs. Below is a basic configuration options to get you started. Read more &lt;a href="https://phpstan.org/config-reference" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;max&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src&lt;/span&gt;
            &lt;span class="s"&gt;- test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the configuration setting above, we can now omit the 3rd argument when running the &lt;code&gt;phpstan&lt;/code&gt; command which is the &lt;code&gt;path&lt;/code&gt; to our source code. This is now a valid command once you have &lt;code&gt;phpstan.neon&lt;/code&gt; on your root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;phpstan&lt;/span&gt; &lt;span class="n"&gt;analyse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the &lt;code&gt;level&lt;/code&gt; set to max, we have more stricter analysis and things like incorrect typehints, incorrect return types, will now throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;phpstan&lt;/span&gt; &lt;span class="n"&gt;analyse&lt;/span&gt;
&lt;span class="nc"&gt;Note&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;Code\demo\photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;library\phpstan&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;neon&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
 &lt;span class="mi"&gt;1&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="o"&gt;============================&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;

 &lt;span class="o"&gt;------&lt;/span&gt; &lt;span class="o"&gt;----------------------------------------------------------------------------------------&lt;/span&gt;
  &lt;span class="nc"&gt;Line&lt;/span&gt;   &lt;span class="nc"&gt;Photo&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;php&lt;/span&gt;
 &lt;span class="o"&gt;------&lt;/span&gt; &lt;span class="o"&gt;----------------------------------------------------------------------------------------&lt;/span&gt;
  &lt;span class="mi"&gt;7&lt;/span&gt;      &lt;span class="nc"&gt;Property&lt;/span&gt; &lt;span class="nc"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$http&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;typehint&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
  &lt;span class="mi"&gt;9&lt;/span&gt;      &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="nc"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;typehint&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
  &lt;span class="mi"&gt;25&lt;/span&gt;     &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="nc"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;specified&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;iterable&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
         &lt;span class="err"&gt;💡&lt;/span&gt; &lt;span class="nc"&gt;Consider&lt;/span&gt; &lt;span class="n"&gt;adding&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Foo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nc"&gt;PHPDoc&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
         &lt;span class="nc"&gt;You&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt; &lt;span class="n"&gt;off&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt; &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;checkMissingIterableValueType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt;
         &lt;span class="n"&gt;Code\demo\photo&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;library\phpstan&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="n"&gt;neon&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
  &lt;span class="mi"&gt;27&lt;/span&gt;     &lt;span class="nc"&gt;Method&lt;/span&gt; &lt;span class="nc"&gt;Photo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;
 &lt;span class="o"&gt;------&lt;/span&gt; &lt;span class="o"&gt;----------------------------------------------------------------------------------------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take note of this line which now tells us that our configuration file is being used to analyse our code:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Using configuration file Code\demo\photo-library\phpstan.neon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code which produced the errors above looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="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;use&lt;/span&gt; &lt;span class="nc"&gt;GuzzleHttp\Client&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;Photo&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;http&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;GuzzleHttp\Client&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'base_uri'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'https://photo.google.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'headers'&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;'Authorization'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Bearer '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Returns an array of photos in the 
     * library
     * 
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'Photos in the library'&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;Since my codebase above is relatively new and I am using PHP 7.4 with strict types enabled, I may have better luck resolving these errors in a few minutes. That may not be the case when you have a large codebase, and you don't have to feel bad for having these errors since you wrote the code without static analysis in mind.&lt;/p&gt;

&lt;p&gt;Editing our &lt;code&gt;phpstan.neon&lt;/code&gt; file and setting the &lt;code&gt;level&lt;/code&gt; to anywhere between 0 and 8 will allow us to make a loose or strict analysis based on the level we settle for.  The &lt;code&gt;max&lt;/code&gt; level will use the strictest value available depending on the version of PHPStan you have. Learn more about the levels &lt;a href="https://phpstan.org/user-guide/rule-levels" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Nip it in the bug :)
&lt;/h3&gt;

&lt;p&gt;Catch your bugs before they get bigger and cause problems. One way I love to do this is by adding phpstan to the scripts section of my &lt;code&gt;composer.json&lt;/code&gt; and running a command to analyse my codebase before pushing to source control. You can also add &lt;code&gt;phpstan&lt;/code&gt; to your travis ci builds and we will see how to do that in a bit.&lt;/p&gt;

&lt;p&gt;Add the following to the scripts section of your composer.json:&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="nl"&gt;"scripts"&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;"analyse"&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="s2"&gt;"phpstan analyse src -c phpstan.neon --level max --no-progress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"phpstan analyse tests -c phpstan.neon --level 4 --no-progress"&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;This adds a script called &lt;code&gt;analyse&lt;/code&gt; to composer which you can run by executing &lt;code&gt;composer run analyse&lt;/code&gt;. That will execute the 2 commands we have specified here:&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="s2"&gt;"phpstan analyse src -c phpstan.neon --level 5 --no-progress"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"phpstan analyse tests -c phpstan.neon --level 5 --no-progress"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command analyses our &lt;code&gt;src&lt;/code&gt; directory and the second analyses the &lt;code&gt;tests&lt;/code&gt; directory. We are passing a couple of arguments which you can almost already tell what they do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;-c phpstan.neon: Tells phpstan to run with the configurations defined in phpstan.neon&lt;/li&gt;
&lt;li&gt;—level: Tells phpstan what level to run the analysis at (5 in this case)&lt;/li&gt;
&lt;li&gt;—no-progress is a special flag to tell phpstan not to report analysis progress as it traverses our codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding phpstan to your Travis builds
&lt;/h3&gt;

&lt;p&gt;This can be achieved by adding the composer script to analyse our codebase in the script section of &lt;code&gt;.travis.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;composer run analyse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only for demonstration purpose, ideally you will want to run other checks which you can group into a composer script in your composer.json file and run that script in your travis build but this is meant to give you an overview of how that is done. &lt;/p&gt;

&lt;p&gt;You can find a sample &lt;code&gt;.travis.yaml&lt;/code&gt; which I use here for my builds &lt;a href="https://github.com/goodhands/comments-sdk/blob/master/.travis.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt; and a sample composer.json file &lt;a href="https://github.com/goodhands/comments-sdk/blob/master/composer.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final notes
&lt;/h3&gt;

&lt;p&gt;Static analysis is something I learned recently and I must say that it gives a unique developer experience. As I am able to write efficient and clean code and catch my errors before they make it to source control. I hope that this article has given you an insight on how static analysis can help you write better code and improve your development process. Please leave your thoughts and comments on &lt;a href="https://twitter.com/devloader" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>testing</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
