Deep Dive into The Laravel Artisan file
Tags: php, laravel
Published: 2020-06-03 19:33:26

<!-- wp:heading -->
<h2>Introduction</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The popular PHP framework, Laravel comes with a CLI tool, <code class="language-bash">artisan</code> that offers a lot of the functionality that makes the framework so useful.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>From preinstalled system commands like <code class="language-bash">$ php artisan migrate</code> to any custom commands you write, you've used artisan.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In this article, we'll explore every line of the artisan file and figure out what they do and how it's all tied together.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>The artisan File</h2>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">#!/usr/bin/env php
&lt;?php
 
define('LARAVEL_START', microtime(true));
 
/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader
| for our application. We just need to utilize it! We'll require it
| into the script here so that we do not have to worry about the
| loading of any our classes "manually". Feels great to relax.
|
*/
 
require __DIR__.'/vendor/autoload.php';
 
$app = require_once __DIR__.'/bootstrap/app.php';
 
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
 
$kernel = $app-&gt;make(Illuminate\Contracts\Console\Kernel::class);
 
$status = $kernel-&gt;handle(
    $input = new Symfony\Component\Console\Input\ArgvInput,
    new Symfony\Component\Console\Output\ConsoleOutput
);
 
/*
|--------------------------------------------------------------------------
| Shutdown The Application
|--------------------------------------------------------------------------
|
| Once Artisan has finished running, we will fire off the shutdown events
| so that any final work may be done by the application before we shut
| down the process. This is the last thing to happen to the request.
|
*/
 
$kernel-&gt;terminate($input, $status);
 
exit($status);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:heading -->
<h2>Line by Line Analysis</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":4} -->
<h4>Line 1</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">#!/usr/bin/env php</code> </pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This line is something called a shebang. A shebang tells the command line where to look for the interpreter for a particular script. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For example, when writing bash scripts it is common to see a shebang such as <code class="language-bash">#!/bin/bash</code> at the top which points to the bash shell that will execute the script. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The shebang in this bash example uses an absolute path to the bash executable while the one from the artisan file uses a logical path. <a rel="noreferrer noopener" aria-label="This UNIX Stack Exchange Question (opens in a new tab)" href="https://unix.stackexchange.com/questions/29608/why-is-it-better-to-use-usr-bin-env-name-instead-of-path-to-name-as-my" target="_blank">This UNIX Stack Exchange Question</a> features some interesting views on the subject.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It only works on UNIX-like systems, so Mac OS X or Linux but not Windows (although, if you use <strong>git bash</strong> it should work).</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the artisan case, our shebang uses the <code class="language-bash">env</code> command to find the first php executable in the user's path, wherever it may be.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Shebangs mostly allow you run scripts in the command line without first calling the interpreter. For example, running artisan commands without prepending <strong>php</strong> to it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can set this up by first making the artisan script executable via <code class="language-bash">chmod +x artisan</code> and then running <code class="language-bash">./artisan &lt;your-command&gt;</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Take note of the dot in front of the artisan. That tells the shell that you want to run that as a command.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The next line is just a regular opening php tag, so we'll skip ahead to line 4.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 4</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">define('LARAVEL_START', microtime(true));</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This line creates a PHP constant  <code class="language-php"><strong>LARAVEL_START</strong></code> and assigns it the value of <code class="language-php"><strong>microtime(true)</strong></code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>According to the PHP Documentation, "<strong><code class="language-php">microtime()</code></strong>&nbsp;returns the current Unix timestamp with microseconds.". It returns a string value by default, but passing the optional <code class="language-php">$get_as_float</code> parameter as <code class="language-php">true</code> returns a float instead.  </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, where does this get used in the framework and what is it for? Well, I ran a quick search on the <a rel="noreferrer noopener" aria-label="laravel/framework repo (opens in a new tab)" href="https://github.com/laravel/framework" target="_blank">laravel/framework repo</a> and didn't find any references to the constant. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>My best guess, is that it's used to test how fast the framework starts up or serves request. You can compare the <code class="language-php">LARAVEL_START</code> value to the value of <code class="language-php">microtime(true)</code> when your request is completed.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I found <a rel="noreferrer noopener" aria-label="this Stack Overflow question and answer (opens in a new tab)" href="https://stackoverflow.com/questions/52882802/what-and-where-comes-the-actual-usage-of-laravel-start-const-defined-in-index-ph" target="_blank">this Stack Overflow question and answer</a> that seems to support my guess. Although, it's asking about the variable in <strong>index.php</strong> (the application entrypoint for web requests just as artisan is the entrypoint for console "requests").</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The next few lines we'll look at feature the first docblock in the artisan file.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Lines 6 - 16</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">/*

|--------------------------------------------------------------------------

| Register The Auto Loader

|--------------------------------------------------------------------------

|

| Composer provides a convenient, automatically generated class loader

| for our application. We just need to utilize it! We'll require it

| into the script here so that we do not have to worry about the

| loading of any our classes "manually". Feels great to relax.

|

*/</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Here we have a docblock describing the composer-provided autoloader and why Laravel uses it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>A fun fact about Taylor Otwell and Laravel's docblock is that (for multiline comments) each line is exactly 3 characters less than the preceding. Go ahead and check for yourself here!</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>And, interestingly, <a rel="noreferrer noopener" aria-label="according to this tweet (opens in a new tab)" href="https://twitter.com/maker_schmitz/status/563929347594420224?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E563929477265121280&amp;ref_url=https%3A%2F%2Fservices.etin.space%2Fnotes%2Fwp-admin%2Fpost.php%3Fpost%3D437%26action%3Dedit" target="_blank">according to this tweet</a>, he did them by hand.</p>
<!-- /wp:paragraph -->

<!-- wp:core-embed/twitter {"url":"https://twitter.com/taylorotwell/status/563929477265121280","type":"rich","providerNameSlug":"twitter","className":""} -->
<figure class="wp-block-embed-twitter wp-block-embed is-type-rich is-provider-twitter"><div class="wp-block-embed__wrapper">
https://twitter.com/taylorotwell/status/563929477265121280
</div></figure>
<!-- /wp:core-embed/twitter -->

<!-- wp:paragraph -->
<p>The next line we'll consider focuses on including the autoloader.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 18</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">require __DIR__.'/vendor/autoload.php';</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This <strong>require</strong> directive loads in the autoload.php file that is included in the vendor directory after successfully running <code class="language-bash">$ composer install</code></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To learn more about how Composer works especially in the context of Laravel I would recommend <a rel="noreferrer noopener" aria-label="this excellent article by Alan Storm on the subject (opens in a new tab)" href="https://alanstorm.com/composer_autoloader_part_1/" target="_blank">this excellent article by Alan Storm on the subject</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next, we'll turn our attention to Line 20 </p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 20</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">$app = require_once __DIR__.'/bootstrap/app.php';</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>This line creates and initializes the <code class="language-php">$app</code> variable with the contents of <strong>/bootstrap/app.php</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>app.php</strong> initializes a new instance of the Laravel application which is basically the <strong>IoC container</strong> and returns that value from the script.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Thus, the <code class="language-php">$app</code> variable contains an instance of our Laravel application and we can basically load and use any parts of the application we want. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For example, using the <code class="language-php">make()</code> method to resolve a class' dependencies and create an instance of it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is exactly the same as what we can do with the <code class="language-php">app()</code> helper method that we use within our code.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next, more comment shenanigans!</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Lines 22 - 31</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">/*

|--------------------------------------------------------------------------

| Run The Artisan Application

|--------------------------------------------------------------------------

|

| When we run the console application, the current CLI command will be

| executed in this console and the response sent back to a terminal

| or another output device for the developers. Here goes nothing!

|

*/</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Here we have another docblock. Once again, with each line 3 characters less than the preceding. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Doing something like this, especially if it's by hand, would have to be difficult.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>I remember watching an episode on <a rel="noreferrer noopener" aria-label="Laracasts (opens in a new tab)" href="https://Laracasts.com" target="_blank">Laracasts</a> where Jeffrey Way says it's just another example of how much care and detail Taylor Orwell puts into the framework. I'm inclined to agree.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This block talks about the app lifecycle from the console command to output along with a cheeky <em>"here goes nothing!"</em>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Next we'll use the <code>$app</code> variable from above on Line 33.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 33</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">$kernel = $app-&gt;make(Illuminate\Contracts\Console\Kernel::class);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>So, here we initialize another variable, <code class="language-php">$kernel</code>, using the app container to resolve <code class="language-php">Kernel</code> class via the <code class="language-php">make()</code> method.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Of course, it's not a concrete class we are passing into the <code>make()</code> method but an interface. This is a great example of <a href="https://notes.etin.space/posts/solid-in-laravel-too-much-or-not-enough" target="_blank" rel="noreferrer noopener" aria-label="the SOLID principles at work in Laravel (opens in a new tab)">the SOLID principles at work in Laravel</a>, particularly the <strong>Liskov Substitution Principle</strong> and <strong>Dependency Inversion</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>It allows us to easily switch out the concrete kernel class that is called if we need to by simply changing the binding of the interface to the concrete class.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Typically, within our own application code, we will register such bindings within a service provider class as <a rel="noreferrer noopener" aria-label="recommended by the Laravel Documentation on the matter (opens in a new tab)" href="https://laravel.com/docs/7.x/container#binding-basics" target="_blank">recommended by the Laravel Documentation on the matter</a>, but in the <strong>artisan</strong> file, such a binding would happen too late.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, instead the binding is done within the <strong>/bootstrap/app.php</strong>. This file binds the different Kernels for console (which is used by artisan) and web as well as the Exception Handler.</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">$app-&gt;singleton(

    Illuminate\Contracts\Http\Kernel::class,

    App\Http\Kernel::class

);

 

$app-&gt;singleton(

    Illuminate\Contracts\Console\Kernel::class,

    App\Console\Kernel::class

);

 

$app-&gt;singleton(

    Illuminate\Contracts\Debug\ExceptionHandler::class,

    App\Exceptions\Handler::class

);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>As we see from the above, the <strong>Kernel</strong> contract resolves to <strong>App\Console\Kernel</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>With the instance of Kernel loaded into the variable, we are now set to run the actual artisan command. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The next few lines we'll consider handle this.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Lines 35-38</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">$status = $kernel-&gt;handle(

    $input = new Symfony\Component\Console\Input\ArgvInput,

    new Symfony\Component\Console\Output\ConsoleOutput

);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Here we assign the output of the <code>$kernel-&gt;handle()</code> method into the <code>$status</code> variable.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If we visit the <strong>App\Console\Kernel</strong> class, we'll find that it inherits from <strong><a rel="noreferrer noopener" aria-label="Illuminate\Foundation\Console\Kernel (opens in a new tab)" href="https://github.com/laravel/framework/blob/7.x/src/Illuminate/Foundation/Console/Kernel.php" target="_blank">Illuminate\Foundation\Console\Kernel</a></strong> which is where the <code class="language-php">handle()</code> method resides.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The method takes two arguments - <code class="language-php">$input</code> and <code class="language-php">$output</code> - runs some bootstrapping to load the providers and other required services before creating an instance of the <a rel="noreferrer noopener" aria-label="artisan application (opens in a new tab)" href="https://github.com/laravel/framework/blob/7.x/src/Illuminate/Console/Application.php" target="_blank">artisan application</a> and calling it's <code class="language-php">run($input, $output)</code> method.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The method returns the status code of the action and it is this value that eventually gets passed into our <code class="language-php">$status</code> variable in the <strong>artisan</strong> file.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The input and output variables we passed to the <code class="language-php">run()</code> method must be instances of <strong>Symfony\Component\Console\Input\InputInterface</strong> &amp; <strong>Symfony\Component\Console\Output\OutputInterface</strong> respectively. This is another example of the two SOLID principles we mentioned earlier. Being able to easily switch out the concrete implementations makes it easier for us to use a different input and output for testing purposes or if our application needs are different.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Up next, we encounter another docblock. </p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Lines 40 - 49</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">/*

|--------------------------------------------------------------------------

| Shutdown The Application

|--------------------------------------------------------------------------

|

| Once Artisan has finished running, we will fire off the shutdown events

| so that any final work may be done by the application before we shut

| down the process. This is the last thing to happen to the request.

|

*/</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>You know the drill by know. Another docblock that leaves me wondering how much time must have gone into phrasing the sentences.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This one talks about the shutdown process for the command.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 51</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">$kernel-&gt;terminate($input, $status);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>To begin the shutdown process, we make a call to the <code>terminate()</code> method on the $kernel instance. Once again, this method is defined on <strong><a rel="noreferrer noopener" aria-label="Illuminate\Foundation\Console\Kernel (opens in a new tab)" href="https://github.com/laravel/framework/blob/7.x/src/Illuminate/Foundation/Console/Kernel.php" target="_blank">Illuminate\Foundation\Console\Kernel</a></strong> and simply calls the terminate() method on the <strong>app</strong> instance. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The <code class="language-php">terminate()</code> method takes in two arguments but appears to do nothing with them.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>And now, the final line.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Line 53</h4>
<!-- /wp:heading -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted"><code class="language-php">exit($status);</code></pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>According to the PHP Docs, this method terminates the execution of a script. It goes on to say the following about the optional $status argument:</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>If&nbsp;<code>status</code>&nbsp;is a string, this function prints the&nbsp;<code>status</code>&nbsp;just before exiting.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><em>"If&nbsp;<code>status</code>&nbsp;is an&nbsp;<a href="https://www.php.net/manual/en/language.types.integer.php">integer</a>, that value will be used as the exit status and not printed. Exit statuses should be in the range 0 to 254, the exit status 255 is reserved by PHP and shall not be used. The status 0 is used to terminate the program successfully."</em></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In exploring the artisan file, I have regained an appreciation for Laravel's architecture. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The entrypoint for web requests (index.php) will feature many of the same structures and ideas.</p>
<!-- /wp:paragraph -->