Jose Jimenez
Jose Jimenez
Software Architect & Developer
> >

Simplify Your Laravel Project Installation with One Custom Command

Published in Laravel, PHP, Database on May 30, 2023

Overview

This article will demonstrate how to create a command to install your Laravel project. The command will ensure that the application is consistent across all team members by executing all the necessary steps to get the application up and running.

Introduction

When working with a Laravel project, you don't want to complicate your life by requiring your team members to run different commands to get your application working. Instead, creating one command that executes everything needed ensures that everything is consistent within everyone's application.

Creating the Command

To create the command, start by running the following command:

1art make:command System/InstallCommand

This will create the command under app/Console/Commands/System. You can create additional directories inside the Commands directory to keep your application more organized. For example, you could lump all system:* commands under the System/ directory.

Here is the code for the InstallCommand:

 1<?php
 2 
 3declare(strict_types=1);
 4 
5namespace App\Console\Commands\System;
 6 
7use App;
8use Illuminate\Console\Command;
 9 
10class InstallCommand extends Command
11{
12 /**
13 * The name and signature of the console command.
14 *
15 * @var string
16 */
17 protected $signature = 'system:install';
18 
19 /**
20 * The console command description.
21 *
22 * @var string
23 */
24 protected $description = 'Install the application on a non-production environment.';
25 
26 /**
27 * Create a new command instance.
28 *
29 * @return void
30 */
31 public function __construct()
32 {
33 parent::__construct();
34 }
35 
36 /**
37 * Execute the console command.
38 *
39 * @return int
40 */
41 public function handle(): int
42 {
43 // Check that the application you are installing has the proper .env configuration
44 if (config('app.name') !== 'myappname') {
45 $this->error('Application name is not myappname.');
46 
47 return Command::FAILURE;
48 }
49 
50 // Check if this command is being run in production
51 if ($this->isRunningInProduction()) {
52 $this->error('Cannot run this command in production.');
53 
54 return Command::FAILURE;
55 }
56 
57 // Create symbolic links
58 $this->info('Create Symbolic links.');
59 $this->call('storage:link', ['--force' => true]);
60 
61 // Clear cached bootstrap files
62 $this->clearCommands();
63 
64 // Migrate and seed a fresh database to work with
65 $this->info('Migrate and seed a fresh database to work with.');
66 $this->call('migrate:fresh', ['--seed' => true]);
67 
68 // Display success message
69 $this->line('[Installation is now complete]', 'info');
70 
71 return Command::SUCCESS;
72 }
73 
74 /**
75 * Check if this command is being run in production
76 *
77 * @return bool
78 */
79 protected function isRunningInProduction(): bool
80 {
81 return App::isProduction() === true;
82 }
83 
84 /**
85 * Clear cached bootstrap files
86 */
87 protected function clearCommands(): void
88 {
89 $this->info('Clearing cached bootstrap files.');
90 
91 // Clear cached bootstrap files such as optimize and queue
92 collect([
93 'optimize' => fn () => $this->callSilent('optimize:clear') == 0,
94 'queue' => fn () => $this->callSilent('queue:clear') == 0,
95 ])->each(fn ($task, $description) => $this->components->task($description, $task));
96 
97 $this->newLine();
98 }
99}

Explanation

When you run the system:install command, several things happen:

  1. The command checks to make sure that the application you are installing has the proper .env configuration. This code checks that config('app.name') matches myappname. This initial check ensures that your environment variables match.
1if (config('app.name') !== 'myappname') {
2 $this->error('Application name is not myappname.');
3
4 return Command::FAILURE;
5}
  1. The command checks whether it is being run in production, to avoid accidentally installing your application on a live server. This method should have more complex logic, check to make sure that specific critical configuration variables hold non-production values in a way to not divulge any sensitive information.
1if ($this->isRunningInProduction()) {
2 $this->error('Cannot run this command in production.');
3
4 return Command::FAILURE;
5}
  1. The command creates the storage links configured:
1$this->call('storage:link', ['--force' => true]);
  1. Your custom command runs optimize:clear, which as of Laravel 10 clears events, views, cache, route, config, and compiled by default. In the code we added an additional item during an app install such as queue:clear, you can check your packages to add additional clear commands.
1$this->clearCommands();
  1. The command runs migrate:fresh with the seed, to drop and create the tables from a fresh state. This allows you to work between separate branches without any issues that are introduced with rollbacks.
1$this->call('migrate:fresh', ['--seed' => true]);
  1. The command displays a message and sends the success signal to instruct the machine running this command that everything installed correctly and fire off any additional commands as needed.
1$this->line('[Installation is now complete]', 'info');

By following these steps and creating a consistent installation process, you can save yourself and your team members time and unnecessary hassle when working on your Laravel project.