Do not speak Portuguese? Translate this site with Google or Bing Translator
Getting Progress Reports With Laravel Commands

Posted on: August 27, 2020 03:33 PM

Posted by: Renato

Categories: Laravel

Views: 1100

The artisan command line tool provided by laravel provides a number of useful commands to help us build our applications. You can run the command

php artisan list

from your project root to list of all available commands. Laravel however does not stop here, the framework provides us with the ability to add our custom console commands to the default command list. These commands are stored in the commands directory

app/Console/Command

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}

So to our example, lets say we need to make an external request to get details about users of our app and due to the intensive nature if this task we decide to schedule a command so we run it periodically. So lets name our command FetchUserInfo, we can go ahead now and create our first Laravel command

php artisan make:command FetchUserInfo

This will create a FetchUserInfo command class under the namespace

App\Console\Commands

 

The signature property allows us to set a custom name for our command which would be used to execute our script. The description property allows us to provide a meaningful description to explain to users what our command does. These two would be shown when you use the list artisan command.

Lets set the signature and description for our command.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Fetch app user information';

}

Skipping the constructor method for now the next thing on our list is the handle method. This method will hold the logic that would run when your command is executed in the console. Its here we’ll place our logic for fetching our user information. We will be using a public api https://reqres.in/ in our example.

To make the requests to our api we would use the guzzle http client. We can install that using composer, instructions can be found here. Lets run the command below from our Laravel project root

composer require guzzlehttp/guzzle

When the command is done running we can verify from the composer.json file the version that was installed by checking the require property. In our case version 6.3 was installed.

"guzzlehttp/guzzle": "^6.3"

With guzzle installed now we can go ahead and complete our handle method with the logic to fetch our user info.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class FetchUsersInfo extends Command
{
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $client = new \GuzzleHttp\Client();
        $pages = collect([1,2,3,4,5]);

        $pages->map(function($page) use($client) {
            $res = $client->request('GET', "https://reqres.in/api/users?page=$page");
            logger($res->getBody());
        });
    }
}

Our handle method simply creates a new guzzle instance, initializes a pages variable with a collection object which receives an array of 5 elements as its argument. We iterate over our collection with the help of the map method and make a request for a specific page from our dummy api. The response we receive is logged.

We can execute our handle method by running the command below

php artisan users:fetch

Now this works, our script is executed and our user information is received. Why do we need progress reports?

Ok, lets just assume our dummy api had rate limits and we could not be making arbitrary calls to fetch for users. This would mean we need a strategy so we do not exceed our limits and get denied our user resource by the api. We could decide to sleep for 30 seconds after every successful request before making another api call.

This strategy would work but lets just imagine a scenario where we have 1000’s of pages and having to sleep after every page. You would not want to be starring at your console wondering when your script would be done executing.

We need more updates from our scripts, so we can go and grab a coffee having an idea of how long we have to wait. Luckily for us Laravel has us covered as usual. Laravel relies heavily on Symfony and it is the same case in this scenario. The Laravel documentation provides a basic example but you can check the Symfony docs for more advanced use cases here .

Lets update our handle method to include progress reports.

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

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

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Fetch app user information';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $client = new \GuzzleHttp\Client();
        $pages = collect([1,2,3,4,5]);
        $progressBar = $this->output->createProgressBar($pages->count());
        $progressBar->start();

        $pages->map(function($page) use($client, $progressBar) {
            $this->output->write("<info> Fetching user info for page => </info>");
            $this->output->write("<info>$page</info>");

            $res = $client->request('GET', "https://reqres.in/api/users?page=$page");

            if($res->getStatusCode() == 200) {
                logger($res->getBody());
            }

            sleep(30);
            $progressBar->advance();
        });
        
        $progressBar->finish();
    }
}

This is how our handle method with progress reporting looks like. We have access to the output method because we are extending

Illuminate\Console\Command;

We can use the output method to generate reports for our console commands. First we call the createProgressBar method and pass it the total count of pages we are going to fetch from our dummy api.

$progressBar = $this->output->createProgressBar($pages->count());

Immediately after that we call the start method to begin drawing our progress bar. We then pass our progress bar object to our $pages map by the using the use keyword.

$pages->map(function($page) use($client, $progressBar) {

We add further information to our progress reports by calling the write method.

$this->output->write("<info> Fetching user info for page => </info>");$this->output->write("<info>$page</info>");

We then call the advance method to move our progress bar after every successful api request.

$progressBar->advance();

Once we are done with our requests and we exit our map iteration, we call the finish method to close the progress bar.

$progressBar->finish();

Now you can go and pick a cup of coffee with confidence knowing perfectly well, how long your Laravel console commands would take to complete. Below is an image of the final output. Thank you for your time

https://medium.com/@winni4eva/getting-progress-reports-when-running-laravel-commands-aafe60ccee0c

 

Image for post
Laravel command progress bar example

0

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 0 Comments

No comments yet! Be the first to comment

Blog Search


Categories

OUTROS (16) Variados (109) PHP (133) Laravel (171) Black Hat (3) front-end (29) linux (114) postgresql (39) Docker (28) rest (5) soap (1) webservice (6) October (1) CMS (2) node (7) backend (13) ubuntu (56) devops (25) nodejs (5) npm (3) nvm (1) git (8) firefox (1) react (7) reactnative (5) collections (1) javascript (7) reactjs (8) yarn (0) adb (1) Solid (2) blade (3) models (1) controllers (0) log (1) html (2) hardware (3) aws (14) Transcribe (2) transcription (1) google (4) ibm (1) nuance (1) PHP Swoole (5) mysql (31) macox (4) flutter (1) symfony (1) cor (1) colors (2) homeOffice (2) jobs (3) imagick (2) ec2 (1) sw (1) websocket (2) markdown (1) ckeditor (1) tecnologia (14) faceapp (1) eloquent (14) query (4) sql (40) ddd (3) nginx (9) apache (4) certbot (1) lets-encrypt (3) debian (12) liquid (1) magento (2) ruby (1) LETSENCRYPT (1) Fibonacci (1) wine (1) transaction (1) pendrive (1) boot (1) usb (1) prf (1) policia (2) federal (1) lucena (1) mongodb (4) paypal (1) payment (1) zend (1) vim (4) ciencia (6) js (1) nosql (1) java (1) JasperReports (1) phpjasper (1) covid19 (1) saude (1) athena (1) cinnamon (1) phpunit (2) binaural (1) mysqli (3) database (42) windows (6) vala (1) json (2) oracle (1) mariadb (4) dev (12) webdev (24) s3 (4) storage (1) kitematic (1) gnome (2) web (2) intel (3) piada (1) cron (2) dba (18) lumen (1) ffmpeg (2) android (2) aplicativo (1) fedora (2) shell (4) bash (3) script (3) lider (1) htm (1) csv (1) dropbox (1) db (3) combustivel (2) haru (1) presenter (1) gasolina (1) MeioAmbiente (1) Grunt (1) biologia (1) programming (22) performance (3) brain (1) smartphones (1) telefonia (1) privacidade (1) opensource (3) microg (1) iode (1) ssh (3) zsh (2) terminal (3) dracula (1) spaceship (1) mac (2) idiomas (1) laptop (2) developer (37) api (5) data (1) matematica (1) seguranca (2) 100DaysOfCode (9) hotfix (1) documentation (1) laravelphp (10) RabbitMQ (3) Elasticsearch (1) redis (2) Raspberry (4) Padrao de design (4) JQuery (1) angularjs (4) Dicas (43) Kubernetes (3) vscode (2) backup (1) angular (3) servers (2) pipelines (1) AppSec (1) DevSecOps (4) rust (1) RustLang (1) Mozilla (1) algoritimo (1) sqlite (1) Passport (2) jwt (5) security (2) translate (1) kube (2) iot (1) politica (2) bolsonaro (1) flow (1) podcast (1) Brasil (1) containers (3) traefik (1) networking (1) host (1) POO (2) microservices (2) bug (1) cqrs (1) arquitetura (3) Architecture (4) sail (3) militar (1) artigo (1) economia (1) forcas armadas (1) ffaa (1) autenticacao (2) autorizacao (2) authentication (4) authorization (3) NoCookies (1) wsl (4) memcached (1) macos (2) unix (2) kali-linux (1) linux-tools (5) apple (1) noticias (2) composer (1) rancher (1) k8s (1) escopos (1) orm (1) jenkins (4) github (5) gitlab (3) queue (1) Passwordless (1) sonarqube (1) phpswoole (1) laraveloctane (1) Swoole (1) Swoole (1) octane (1) Structurizr (1) Diagramas (1) c4 (1) c4-models (1) compactar (1) compression (1) messaging (1) restfull (1) eventdrive (1) services (1) http (1) Monolith (1) microservice (1) historia (1) educacao (1) cavalotroia (1) OOD (0) odd (1) chatgpt (1) openai (3) vicuna (1) llama (1) gpt (1) transformers (1) pytorch (1) tensorflow (1) akitando (1) ia (1) nvidia (1) agi (1) guard (1) multiple_authen (2) rpi (1) auth (1) auth (1) livros (2) ElonMusk (2) Oh My Zsh (1) Manjaro (1) BigLinux (2) ArchLinux (1) Migration (1) Error (1) Monitor (1) Filament (1) LaravelFilament (1) replication (1) phpfpm (1) cache (1) vpn (1) l2tp (1) zorin-os (1) optimization (1) scheduling (1) monitoring (2) linkedin (1) community (1) inteligencia-artificial (2) wsl2 (1) maps (1) API_KEY_GOOGLE_MAPS (1) repmgr (1) altadisponibilidade (1) banco (1) modelagemdedados (1) inteligenciadedados (4) governancadedados (1) bancodedados (2) Observability (1) picpay (1) ecommerce (1) Curisidades (1) Samurai (1) KubeCon (1) GitOps (1) Axios (1) Fetch (1) Deepin (1) vue (4) nuxt (1) PKCE (1) Oauth2 (2) webhook (1) TypeScript (1) tailwind (1) gource (2)

New Articles



Get Latest Updates by Email