One place for hosting & domains

      Artisan

      Automate Tasks by Creating Custom Artisan command in Laravel

      Introduction

      Out of the box, Laravel comes installed with a lot of helpful commands available to use in an application. But as your application grows, you might find it time-wasting, performing some tasks like populating databases with user data or products.

      At this point, automating those tasks will go a long way to help you get data into your database seamlessly and facilitate the rapid completion of your web application.

      Some of the default Artisan commands for Laravel include php artisan serve, php artisan make:controller, php artisan make:model, and so on.

      In this article, we will be creating an artisan command to populate the database with product data. This tutorial will not only show you how to create a custom artisan command but more so to read data from a CSV file, parse and store it in our database using the command we are going to create.

      To get started with the custom artisan command, I want to assume that you already have Laravel installed, if not quickly do that with the following commands. As of the time of writing this tutorial, Laravel 5.5 is being used.

      1. composer create-project --prefer-dist laravel/laravel command

      The command will create a Laravel project called command in your local directory. Feel free to change as preferred.

      Now that you have installed Laravel, let’s proceed to build our own custom commands as stated earlier.
      To create a custom command, use the command:

      1. php artisan make:command productData

      The intention is to create a custom command to populate the products table, hence the reason for the name productData. After successfully running this command, a new class will be created in the app/Console/Commands directory within your project.

      Open app/Console/Commands/productData, you should have content similar to:

      app/Console/Commands/productData.php

      <?php
      
      namespace App\Console\Commands;
      
      use Illuminate\Console\Command;
      
      class productData extends Command
      {
          
          protected $signature = 'command:name';
          
          protected $description = 'Command description';
          
          public function __construct()
          {
              parent::__construct();
          }
          
          public function handle()
          {
              
          }
      }
      

      Now proceed to create the actual command by editing the file we just created:

      app/Console/Commands/productData.php

      <?php
      
      namespace App\Console\Commands;
      
      use App\Product;
      use Illuminate\Console\Command;
      
      class productData extends Command
      {
          
          protected $signature = 'add:product';
      
          
          protected $description = 'Add products data to the database';
      
          public function __construct()
          {
              ...
          }
      
          public function handle()
          {
              
          }
      }
      

      Here, we have changed the name and signature of the command and also added the command description. This will be used when displaying the command on the list screen.

      We are close, but unfortunately, our newly created command will have no effect yet; as it does not exist, as far as Laravel is concerned. To change this, we will need to register the command by navigating to app/Console/kernel.php file and place the Command class we just created in the protected $commands array.

      app/Console/kernel.php

      <?php
      
      namespace App\Console;
      
      use Illuminate\Console\Scheduling\Schedule;
      use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
      
      class Kernel extends ConsoleKernel
      {
          
          protected $commands = [
              Commands\productData::class,
          ];
      
          protected function schedule(Schedule $schedule)
          {
             ...
          }
      
      
          protected function commands()
          {
             ...
          }
      }
      

      To check if the command has been registered, run the artisan command:

      1. php artisan list

      And that’s it, our command signature and description have been successfully registered as indicated above.

      Congratulations! You just created your first custom Artisan command!

      In order to give our command life, we are going to create a model and migration file for Product, and then complete a function that will execute the console command we created.

      Generate a model and migration file with this command:

      1. php artisan make:model Product -m

      This will generate two separate files app/Product and database/migrations/create_products_table. Add the contents below respectively:

      app/Product.php

      ...
      class Product extends Model
      {
      
          protected $table = "products";
          
          protected $fillable = [
            'name', 'description', 'quantity'
          ];
      }
      

      And:

      database/migrations/create_products_table.php

      <?php
      ...
      class CreateProductsTable extends Migration
      {
      
          public function up()
          {
              Schema::create('products', function (Blueprint $table) {
                  $table->increments('id');
                  $table->string('name');
                  $table->string('description');
                  $table->string('quantity');
                  $table->timestamps();
              });
          }
      
      
          public function down()
          {
              ...
          }
      }
      

      Open the .env file and add your database details

      DB_CONNECTION=mysql
      DB_HOST=127.0.0.1
      DB_PORT=3306
      DB_DATABASE=your-database-name
      DB_USERNAME=your-database-username
      DB_PASSWORD=your-database-password
      

      Now run to create tables

      1. php artisan migrate

      Once you execute the newly created command, the handle method within productData class will be called. So let’s edit that and place the required command logic in this method.

      app/Console/Commands/productData.php

      <?php
      ...
      class productData extends Command
      {
      
          protected $signature = 'add:product';
      
          protected $description = 'Add products data to the database';
      
          public function __construct()
          {
              ...
          }
      
          
          public function handle()
          {
              $CSVFile = public_path('products.csv');
              if(!file_exists($CSVFile) || !is_readable($CSVFile))
                  return false;
      
              $header = null;
              $data = array();
      
              if (($handle = fopen($CSVFile,'r')) !== false){
                  while (($row = fgetcsv($handle, 1000, ',')) !==false){
                      if (!$header)
                          $header = $row;
                      else
                          $data[] = array_combine($header, $row);
                  }
                  fclose($handle);
              }
      
              $dataCount = count($data);
              for ($i = 0; $i < $dataCount; $i ++){
                  Product::firstOrCreate($data[$i]);
              }
              echo "Products data added successfully"."\n";
          }
      }
      
      

      You can find the sample CSV file used above here.

      It’s time to see our custom command at work.

      Run

      1. php artisan add:product

      You should get a response stating Product data added successfully after running that command.

      A quick look at what we now have in the database.

      There is a lot more you can effortlessly achieve by creating a custom Artisan command. You can build on this and create more awesome commands to make development very easy for you when using Laravel.

      As shown in this tutorial, you can also read data from a CSV file and store it into your database with just a single command line. I hope this tutorial has been very helpful. If you have any questions or thoughts that require clarifications, kindly drop a comment.

      How To Create Artisan Commands To Manage Database Records in Laravel



      Part of the Series:
      How To Build a Links Landing Page in PHP with Laravel and Docker Compose

      Laravel is an open-source PHP framework that provides a set of tools and resources to build modern PHP applications. In this project-based tutorial series, you’ll build a Links Landing Page application with the Laravel framework, using a containerized PHP development environment managed by Docker Compose.

      At the end, you’ll have a one-page website built with Laravel and managed via Artisan commands where you can share relevant links to an audience on social channels and presentations.

      If you followed along with this series so far, your database tables should be all set. However, you still need to implement a way to let users insert new entries in the links table.

      To limit the scope of this series while also making the application fully-functional, you’ll set up Artisan commands to create and delete links in the database. Artisan is the command line tool that comes with Laravel, offering a number of utilities to speed up the development process, from generating boilerplate code to deleting and re-creating the application’s database.

      Using the command line interface to manage your application can be an alternative to web forms and secured areas, since it requires a user to be logged on the server in order to execute such commands instead of being authenticated from a browser. If you decide later on to create a secured area for your application, you can create web forms to allow a registered user to submit a new link to the database.

      Artisan commands are often used to perform application tasks that should run in the background, either manually or automatically via a scheduling mechanism such as Crontab. They can also be used to facilitate prototyping new application features that need to be configured dynamically, depending on input from an authorized user.

      To get started, create a new Artisan command using the make:command helper:

      • docker-compose exec app php artisan make:command LinkNew

      Output

      Console command created successfully.

      This will create a file named LinkNew.php, located at the app/Console/Commands directory. In this class, which extends from the IlluminateConsoleCommand parent class, you’ll need to implement a handle method that will be executed when this command is called. To define the signature of the command, you’ll set the $signature protected property to link:new.

      Open the new file using your text or code editor of choice. Here, we’ll use nano:

      • nano app/Console/Commands/LinkNew.php

      A few different things will need to happen in the handle method so that you are able to save a new link to the database. First, you’ll prompt for the user’s input in order to obtain the link URL.

       $url = $this->ask('Link URL:');
      

      Then, you’ll use the filter_var function to validate that the input obtained from the user is a valid URL. If the link is invalid, you’ll show an error and exit the application with status code 1, which means the application exited in error.

              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      

      If the link is valid, you’ll continue and ask for the link description using the same method as before.

       $description = $this->ask('Link Description:');
      

      You’ll then ask for a final confirmation that all data is correct, using the confirm helper. If the user confirms, the link is finally inserted in the database. You’ll use the Link Eloquent model created in a previous part of this series to interact with the database.

              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
      
              if ($this->confirm('Is this information correct?')) {
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $link->save();
      
                  $this->info("Saved.");
              }
      

      The application exits with a 0, representing a success status (0 errors).

      return 0;
      

      The following code contains the full implementation of these steps. Replace the current content in your LinkNew class with:

      app/Console/Commands/LinkNew.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkNew extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:new";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Create a New Link';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $url = $this->ask('Link URL:');
      
              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      
              $description = $this->ask('Link Description:');
      
              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
      
              if ($this->confirm('Is this information correct?')) {
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $link->save();
      
                  $this->info("Saved.");
              }
      
              return 0;
          }
      }
      

      Save and close the file when you’re done.

      To execute the command and insert a new link in the database, run:

      • docker-compose exec app php artisan link:new

      Output

      Link URL:: > https://digitalocean.com/community Link Description:: > DigitalOcean Community New Link: https://digitalocean.com/community - DigitalOcean Community Is this information correct? (yes/no) [no]: > yes Saved.

      Feel free to add a few more links if you want to.

      Next, you’ll need to create a new Artisan command to show the list of all links.You can call it link:list. Create the new command with:

      • docker-compose exec app php artisan make:command LinkList

      Open the command class using your text or code editor of choice:

      • nano app/Console/Commands/LinkList.php

      Within the handle method of this command, you’ll query for all rows in the links table. You can use the Link model to access the underlying database query methods that Eloquent provides. To exhibit the results nicely in the command line, you can use the table output helper:

              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
      

      The following code contains the full implementation of the link:list command. Replace the content in your LinkList.php file with :

      app/Console/Commands/LinkList.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      
      class LinkList extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:list";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'List links saved in the database';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
          }
      }
      

      Save and close the file when you are done.

      To run this command and show a list of all links already inserted in the linkstable, run:

      • docker-compose exec app php artisan link:list

      Output

      +----+------------------------------------+--------------+ | id | url | description | +----+------------------------------------+--------------+ | 1 | https://digitalocean.com/community | DO Community | | 2 | https://laravel.com | Laravel | +----+------------------------------------+--------------+

      Finally, you’ll create a command to delete links:

      • docker-compose exec app php artisan make:command LinkDelete

      Output

      Console command created successfully.

      Open the new file using your text or code editor of choice:

      • nano app/Console/Commands/LinkDelete.php

      You can name this command link:delete. To know which link must be deleted, you’ll need to require that users provide an additional argument when calling the command: the ID of the link. This is also set within the $signature variable, which defines how your command is called and what arguments, mandatory or not, should be provided:

      protected $signature="link:delete {link_id}";
      

      The handle method for this command will implement a few different instructions. First, you’ll obtain the Link ID that should have been provided within the command call.

      $link_id = $this->argument('link_id');
      

      Then, you’ll obtain the referenced link from the database, using the Eloquent method find that is available through your Link model.

      $link = Link::find($link_id);
      

      When the find method doesn’t find a database record with that ID, it will return null. You’ll check if that is the current value contained in the $link variable, and return an error in that case. The program will exit in error (code 1).

              if ($link === null) {
                  $this->error("Invalid or non-existent link ID.");
                  return 1;
              }
      

      When $link is not null, the command continues execution. You then use the confirm helper to ask for a user confirmation.

      if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
          // deletes link
      }
      

      When the user confirms the action by typing yes and hitting ENTER, you’ll call the delete method from the Link Eloquent model to delete the specified link from the database.

                  $link->delete();
                  $this->info("Link deleted.");
      

      The following code contains the full implementation for the list:delete command. Replace the content in your LinkDelete.php file with the following:

      app/Console/Commands/LinkDelete.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkDelete extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:delete {link_id}";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Deletes a link from the database.';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $link_id = $this->argument('link_id');
              $link = Link::find($link_id);
      
              if ($link === null) {
                  $this->error("Invalid or non-existent link ID.");
                  return 1;
              }
      
              if ($this->confirm('Are you sure you want to delete this link? ' . $link->url)) {
                  $link->delete();
                  $this->info("Link deleted.");
              }
      
              return 0;
          }
      }
      

      Save and close the file when you’re done.

      Now when you want to delete a link from your links table, you’ll first need to obtain the link’s ID with artisan link:list, as demonstrated earlier on. Once you know the ID of a link, you can run the artisan link:delete command with:

      • docker-compose exec app php artisan link:delete LINK_ID

      Output

      Are you sure you want to delete this link? https://laravel.com (yes/no) [no]: > yes Link deleted.

      You’re now able to insert, list, and delete links in the application’s database, using Artisan commands executed from a command-line interface. In the next part of this series, you’ll set up the front end of your application using Blade templates and the Bulma CSS framework.



      Source link