phpcronlaravel-5.8

How I can execute a command at a specific date and time in laravel 5.8?


Ι need to be able to schedule a command to run in specific date and time.

I have the following doomsday nuking command:

<?php

namespace App\Console\Commands;

class DommdayCommand extends Command
{

  protected $signature='nuke:country {commander} {country} ';
  protected $description="Nuke a country";

  public function handle()
  {
    $dictator= $this->argument('commander');
    $country= $this->argument('country');

    $this->output("Nuking the {$country} from {$dictator} ");
  }
}

And I have a specific schedule:

Person A will nuke Country Z at 2021-06-12 13:00
Person B will nuke Country Z at 2021-06-15 18:00
Person C will nuke Country Y at 2021-06-15 06:00
...

So how I can write date-specific schedules that will execute a specific command at a specific date and time only once? The existing documentation allows me to schedule a command that will be executed continioucly at a specific date and time, for example every hour or every day.

So how I can specify a specific date that will be executed.

Existing cron() function allows me to controll the execution on hour,minute,month,day and day of week. But it does not allow me to specify the year of execution. In my case the year of execution is also important as well. (We do not want to re-nuke an already nuked country from a specific commander also nuking in the next year also not viable as well).

For example if I specify the following in my Kernel.php:

  $schedule->command(DommdayCommand::class)->cron('13 00 15 02 *')

Will execute the command at 2021-02-15 13:00 but also will execute the command at 2022-02-15 13:00 witch I do not want to. I only want to be executed at 2021-02-15 13:00 and never to be executed again.


Solution

  • In accordance to documentation you can use cron to check the:

    Of execution upon a console command. Though it may cause to run every month date hour and minute you specify on cron but you can call a closure as seen in this piece of documentation. Therefore you can use a closure you the year check at Kernel.php.

    use Carbon\Carbon;
    use Illuminate\Support\Facades\Artisan
    
    
    class Kernel extends ConsoleKernel
    {
      
      // Some code exists here
      
      protected function schedule(Schedule $schedule): void
      {
    
          // Rest of schedules
    
           $schedule->call(function () {
                   $year = Carbon::now()->y;
                   if($year == 2021){
                      Artisan::call('nuke:country "Kim Young Un" Amerika');
                    }
            })->cron('13 00 12 06 *');
    
    
          // More schedules
    
      }
    
      // Rest of code here
    }
    

    Therefore use a closure to check for the year and then if year is the appropriate one then call the code whilst on cron expression you check for month, day, hour and minute of execution.

    An alternative approach is to let the closure handle it all:

    $schedule->call(function () {
    
      $dates=[
        '2021-06-12 13:00' => [
           'commander'=>'Kim Young Un',
           'country'  => 'America'
         ],
         '2021-06-15 18:00' => [
           'commander'=>'Osama Bin Laden\'s clone',
           'country'  => 'America'
         ],
         '2021-06-15 06:00' => [
           'commander'=>'Adolf Hitler\'s clone',
           'country'  => 'Israel'
         ],
      ];  
    
      $date = Carbon::now()->format('Y-m-d H:i:s');
      
      if(isset($dates[$date])){
         $params=$dates[$date];
         Artisan::call("nuke:country \"{$params['commander']}\" {$params['country']}");
      }
    })->cron('*****');
    

    In other words, execute the command on appropriate dates and continuously check execution date is appropriate.