Creating Installer of your Laravel Project

  • Posted by Sharad Jaiswal

    Creating Installer of Laravel Project to automate basic tasks of the project

    In this article, I am going to show you how to create an installer of Laravel project to automate basic tasks.

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

    • Giving 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.

    Step 1: Setting 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 code below 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 of by this script. You can modify the script / InstallApplication code as per your project needs.

    Thank you!

     

Please Login or Register to leave a response.

Related Articles

Laravel Tutorials

Laravel 5.5 Middleware complete Tutorial

In Laravel, you can think middleware as a system or tool that are used to filter all HTTP requests entering your application. Middleware works between request and response of our application. It sits ..

Laravel Tutorials

Laravel Pagination Ajax

Creating Ajax based pagination is Laravel 5.6. Ajax (Asynchronous JavaScript and XML) is a technique to update a specific part of webpage asynchronously without reloading the page. In this article, we..

Laravel Tutorials

Laravel Pagination

According to Wikipedia Pagination is a process of separating or dividing a document or digital contents into discrete pages. In Core PHP and other frameworks, paginating record is a painful task. Lara..