Creating Installer for Laravel Project

When you are working on a laravel project there is some basic setup that needs to be done for each install of the project.
Like

  • Permissions for “bootstrap/cache”, “storage”, “vendor” folder
  • composer install / composer update
  • Copying .env.example to .env
  • Key generation
  • Migration & Seeding
  • NPM install

Instead of asking your user to do these steps we can create an installer for doing this task. In this blog, we are going to learn to create the installer for laravel projects.

We will use a shell script to do this.

A shell script is a computer program designed to be run by the Unix shell, a command-line interpreter. [Wikipidea]

Step 1: Permissions for different folders

The general permission for folders should be 775. The command for this will be:

sudo chmod -R 775 storage/ bootstrap/cache/ vendor/

Note: If there is any issue you can try with permission 777 [Not Recommended], or you can do this step manually to avoid any issues in the future.

Step 2: Installing Composer dependency

The command to do this is:

composer install

Step 3: Setting up .env

The commands that we need to do this are,

cp .env.example .env

# This line is here because we will update .env from command line
sudo chmod 777 .env

Step 4: Setting Up DB, Migrations & Seeding

For this, we will create a Laravel Console command. For more on Laravel Console please follow official documentation.

Let’s look at the file and then we will understand how each method is working

namespace App\Console\Commands;

use Illuminate\Console\Command;
use DB;

class InstallAppliction extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'application:install';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'This will install the application & set up DB';

    /**
     * Create a new command instance.
     *
     * @return void|mixed
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->line("You can use Ctrl+C to exit the installer any time.\n");
        $this->createDatabase();
        $this->migrate();
        $this->seed();
        $this->setUpKey();
    }

    /** 
     * This method creates the database by taking inputs from the user. 
     * 
     * @return void 
    */ 
    private function createDatabase(){
        if($this->testDbConnection()){
            return;
        }

        $this->line("You need to choose a database type.");

        install_database:

        $connection = null;
        $host = null;
        $port = null;
        $database = null;
        $username = null;
        $password = null;

        $available_connections = array_keys(config('database.connections'));
        $connection = $this->choice('Choose a connection type', $available_connections);

        if($connection == "sqlite"){
            $path = database_path('database.sqlite');
            touch($path);
            $this->info('Database file created at ' . $path);
        } else{
            $defaultPort = $connection == "mysql" ? 3306 
                               : ($connection == "pgsql" ? 5432 : null);

            $host = $this->ask('Database host', 'localhost');
            $port = $this->ask('Database port', $defaultPort);
            $database = $this->ask('Database name');
            $username = $this->ask('Database username');
            $password = $this->secret('Database password');
        }

        $settings = compact('connection', 'host', 'port', 'database', 'username', 'password');
        $this->updateEnvironmentFile($settings);

        if(!$this->testDbConnection()){
            $this->error('Could not connect to database.');
            goto install_database;
        }
    }

    /** 
     * This method is to test the DB connection. 
     * 
     * @return boolean 
    */ 
    private function testDbConnection(){
        $this->line('Checking DB connection.');

        try{
            DB::connection(DB::getDefaultConnection())->reconnect();
        }catch(\Exception $e){
            return false;
        }

        $this->info('Database connection working.');
        return true;
    }

    /**
     * Updates the environment file with the given database settings.
     *
     * @param  string  $settings
     * @return void
     */
    private function updateEnvironmentFile($settings)
    {
        $env_path = base_path('.env');
        DB::purge(DB::getDefaultConnection());

        foreach($settings as $key => $value){
            $key = 'DB_' . strtoupper($key);
            $line = $value ? ($key . '=' . $value) : $key;
            putenv($line);
            file_put_contents($env_path, preg_replace(
                '/^' . $key . '.*/m',
                $line,
                file_get_contents($env_path)
            ));
        }

        config()->offsetSet("database", include(config_path('database.php')));

    }

    /** 
     * Migrate the Database. 
     * 
     * @return void 
    */ 
    private function migrate(){
        $this->line("\nStarting DB Migration...");
        $this->call('migrate');
    }

    /** 
     * Seeds the Database. 
     * 
     * @return void 
    */ 
    private function seed(){
        $this->line("\nStarting DB Seeding...");
        $this->call('db:seed');
    }

    /** 
     * Sets up the application key. 
     * 
     * @return void 
    */ 
    private function setUpKey(){
        $this->call('key:generate');
        $this->info("\nApplication installation completed!");
    }
}

“handle”: This method is the starting point of this command. This method prints a line and then call other methods for installation.

“createDatabase”: This method is responsible for creating the database. This method checks the DB connection first if the connection is successful then it returns as DB is already set up. If DB connection is not set up then it asks for DB username password port etc and sets up the DB. This method uses ask and secret method provided by Laravel Console. Also if you see closely you will find “install_database;“, which is a goto label defining the section for installing the database. After getting input from the user we will try to connect to the DB again if it works we will return to the handle method else we will again come back to this section to start the DB install process all over again.

“testDbConnection”: This method tests the default DB connection and returns the result.

“updateEnvironmentFile”: This method takes a key value array and replace the values for all the keys in .env file using string pattern matching.

“migrate”: This method starts the DB migration process.

“seed”: This method starts the DB seeding process.

“setUpKey”: This method sets up the environment key.

This file needs to be called from the shell script. For this add the following to the script.

php artisan application:install

Step 5: Running NPM install

For installing node packages add this to the installation shell script.

npm install

 

So, the shell script will look like the following :

#!/bin/sh

#Update the folder permissions
sudo chmod -R 775 storage/ bootstrap/cache/ vendor/

# Install Composer Dependency
composer install

# Copy .env.example to .env
cp .env.example .env

# Update permission for .env
# This line is here because we will update .env from command line
sudo chmod 777 .env

#Start the installation process
php artisan application:install

# Install node dependency
npm install

Ok. So we have the installation script ready. Save it as “installer.sh” in the root directory of the project. We can commit this to SCM[GIT/SVN].

 

Now whenever someone downloads the project source code we will have this installer.sh present. We just need to execute the script and our project will be ready to use.

To execute this script we will have to run the following commands after downloading the project

sudo chmod +x installer.sh
sudo ./installer.sh

Now the rest will be taken care by this script. You can modify the script / InstallAppliction code as per your project needs.

Hope this helps.

Happy Coding. 🙂

3 thoughts on “Creating Installer for Laravel Project

  1. I’m not sure the place you are getting your info, however great topic. I must spend some time learning much more or figuring out more. Thank you for fantastic info I used to be in search of this info for my mission.

    Like

  2. You actually make it seem so easy along with your presentation but I to find this matter to be actually something which I believe I’d by no means understand. It sort of feels too complex and extremely broad for me. I am taking a look forward in your next put up, I’ll try to get the cling of it!

    Like

Leave a comment