команда php artisan не работает из-за пользовательской команды

#php #laravel

Вопрос:

Я работал над проектом, в котором необходим планировщик, и нашел решение, вызывая команду каждую минуту. Я зарегистрировал класс в $commands переменной в Kernel , и как только я попытался обслужить приложение, оно просто не работает и не отправляет никакого ответа.

SchedulerDaemon:

 <?php

namespace AppConsoleCommands;

use IlluminateConsoleCommand;
use IlluminateSupportFacadesArtisan;

use CarbonCarbon;

use AppActivityLog;
use AppBooking;
use AppNews;

use DB;
use Exception;
use Log;
use Mail;

class SchedulerDaemon extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'schedule:cron {--queue}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Run the scheduler without cron (For use with Heroku etc)';

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

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle() {
        $this->info('Waiting '. $this->nextMinute(). ' for next run of scheduler');
        sleep($this->nextMinute());
        $this->runScheduler();
    }

    /**
     * Main recurring loop function.
     * Runs the scheduler every minute.
     * If the --queue flag is provided it will run the scheduler as a queue job.
     * Prevents overruns of cron jobs but does mean you need to have capacity to run the scheduler
     * in your queue within 60 seconds.
     *
     */
    protected function runScheduler() {
        // $fn = $this->option('queue') ? 'queue' : 'call';

        $this->info('Running scheduler');

        // Artisan::$fn('schedule:run');
        $this->updateBookings();

        $this->info('completed, sleeping..');
        sleep($this->nextMinute());
        $this->runScheduler();
    }

    /**
     * Works out seconds until the next minute starts;
     *
     * @return int
     */
    protected function nextMinute() {
        $current = Carbon::now();
        return 60 -$current->second;
    }

    private function updateBookings() {
        if (Carbon::now()->timezone('Asia/Manila')->format('h:i') == '07:00' || Carbon::now()->timezone('Asia/Manila')->format('h:i') == '10:00')
            $stoppedAt = null;
            try {
                $bookings = Booking::where('pickup_date', '=', Carbon::now()->timezone('Asia/Manila')->format('Y-m-d'))
                    ->where('status', '=', '2')
                    ->get();

                Log::info($bookings);

                foreach ($bookings as $b) {
                    DB::beginTransaction();
                    Mail::send(
                        'templates.emails.pickup',
                        ['booking' => $b, 'status' => 'pickup'],
                        function ($m) use ($b) {
                            $m->from('no-reply@kane.com');
                            $m->to($b->user->email, $b->user->getName())
                                ->subject('Pick up Status');
                        }
                    );

                    $b->status = 3;
                    $b->save();

                    $stoppedAt = $b->user;

                    DB::commit();
                }

                ActivityLog::log('Updating all bookings with pick up date set for today.', 0);
                ActivityLog::log('Sending emails to all clients with pick up date set for today.', 0);
            } catch (Exception $e) {
                ActivityLog::log('Daily booking update and mailing task failed (stopped at '.$stoppedAt->email.'): '.$e->getMessage(), 0);
                Log::error($e);
                DB::rollback();
            }
        }
    }
}
 

Ядро

 <?php

namespace AppConsole;

use IlluminateSupportFacadesHttp;
use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;

use CarbonCarbon;

use AppActivityLog;
use AppBooking;
use AppNews;

use DB;
use Exception;
use Log;
use Mail;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        // CommandsSchedulerDaemon::class
    ];

    /**
     * Define the application's command schedule.
     *
     * @param IlluminateConsoleSchedulingSchedule $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule) {
        // UPDATE BOOKINGS FOR THAT DAY
        // $schedule->call(function() {
        //  $stoppedAt = null;
        //  try {
        //      $bookings = Booking::where('pickup_date', '=', Carbon::now()->timezone('Asia/Manila')->format('Y-m-d'))
        //          ->where('status', '=', '2')
        //          ->get();

        //      // Log::info($bookings);

        //      foreach ($bookings as $b) {
        //          DB::beginTransaction();
        //          Mail::send(
        //              'templates.emails.pickup',
        //              ['booking' => $b, 'status' => 'pickup'],
        //              function ($m) use ($b) {
        //                  $m->from('no-reply@kane.com');
        //                  $m->to($b->user->email, $b->user->getName())
        //                      ->subject('Pick up Status');
        //              }
        //          );

        //          $b->status = 3;
        //          $b->save();

        //          $stoppedAt = $b->user;

        //          DB::commit();
        //      }

        //      ActivityLog::log('Updating all bookings with pick up date set for today.', 0);
        //      ActivityLog::log('Sending emails to all clients with pick up date set for today.', 0);
        //  } catch (Exception $e) {
        //      ActivityLog::log('Daily booking update and mailing task failed (stopped at '.$stoppedAt->email.'): '.$e->getMessage(), 0);
        //      Log::error($e);
        //      DB::rollback();
        //  }
        // })
        // // ->everyFiveMinutes()
        // ->timezone('Asia/Manila')
        // ->twiceDaily(7, 10)
        // ->name('daily-pickup-mailer')
        // ->withoutOverlapping();

        // $schedule->call(function() {
        //  try {
        //      DB::beginTransaction();

        //      $queryString = http_build_query([
        //          'access_key' => env('MEDIASTACK_ACCESS_KEY'),
        //          'countries' => 'ph',
        //          'date' => Carbon::yesterday()->format('Y-m-d').','.Carbon::now()->format('Y-m-d'),
        //          'limit' => 1
        //      ]);

        //      $ch = curl_init(sprintf('%s?%s', 'https://api.mediastack.com/v1/news', $queryString));
        //      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //      $json = curl_exec($ch);
        //      curl_close($ch);
        //      $response = json_decode($json, true);

        //      DB::commit();
        //  } catch (Exception $e) {
        //      ActivityLog::log('Failed to fetch new news for today.');
        //      DB::rollback();
        //  }
        // })
        // ->timezone('Asia/Manila')
        // ->daily()
        // ->name('daily-news-fetcher')
        // ->withoutOverlapping();
    }
}
 

Как только я прокомментировал SchedulerDaemon в ядре, ремесленник работает нормально, как будто ничего не произошло.

Ответ №1:

Вы должны изменить свой класс ядра.

 <?php

namespace AppConsole;

use IlluminateConsoleSchedulingSchedule;
use IlluminateFoundationConsoleKernel as ConsoleKernel;
use AppConsoleCommandsSchedulerDaemon;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        SchedulerDaemon::class
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  IlluminateConsoleSchedulingSchedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('schedule:cron')->everyMinute();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}