Get an array of scheduled tasks
Asked Answered
U

4

14

Using the Laravel task scheduler I have created a number of tasks in app/Console/Kernel.php

e.g:

$schedule->command('some:command')
    ->daily();

$schedule->command('another:command')
    ->daily();

I would like to display the list of scheduled commands, their frequency, and last/next run time on a dashboard but I'm not sure how I can get the list of scheduled events. Is there a way to do this?

Unattended answered 22/2, 2016 at 17:15 Comment(1)
Here is a way to get it as array for a controller: https://mcmap.net/q/827126/-is-there-a-way-to-get-the-scheduled-task-as-an-array-from-a-controller-duplicateInvolucre
D
32

There's actually no support out of the box for this, unfortunately. What you'll have to do is extend the artisan schedule command and add a list feature. Thankfully there's a simple class you can run:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Console\Scheduling\Schedule;

class ScheduleList extends Command
{
    protected $signature = 'schedule:list';
    protected $description = 'List when scheduled commands are executed.';

    /**
     * @var Schedule
     */
    protected $schedule;

    /**
     * ScheduleList constructor.
     *
     * @param Schedule $schedule
     */
    public function __construct(Schedule $schedule)
    {
        parent::__construct();

        $this->schedule = $schedule;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $events = array_map(function ($event) {
            return [
                'cron' => $event->expression,
                'command' => static::fixupCommand($event->command),
            ];
        }, $this->schedule->events());

        $this->table(
            ['Cron', 'Command'],
            $events
        );
    }

    /**
     * If it's an artisan command, strip off the PHP
     *
     * @param $command
     * @return string
     */
    protected static function fixupCommand($command)
    {
        $parts = explode(' ', $command);
        if (count($parts) > 2 && $parts[1] === "'artisan'") {
            array_shift($parts);
        }

        return implode(' ', $parts);
    }
}

This will provide you with a php artisan schedule:list. Now that's not exactly what you need, but then you can easily get this list from within your Laravel stack by executing:

Artisan::call('schedule:list');

And that will provide you with a list of the schedule commands.

Of course, don't forget to inject the Facade: use Illuminate\Support\Facades\Artisan;

Dennisedennison answered 22/2, 2016 at 17:25 Comment(3)
This works great on the command line... But when i call this from my controller code via Artisan::call('schedule:list'); i just seem to get an exit code of 0. I was hoping to return an array of scheduled $tasks I can loop through and display in my page (or even the simple string output of the above command would be fine to display). Anyway to achieve this?Huntress
EDIT: got at least the output by calling Artisan::output() right afterwards, storing in variable, and displaying in page within a <pre> tag.Huntress
@Huntress I found a way to get it as array: https://mcmap.net/q/827126/-is-there-a-way-to-get-the-scheduled-task-as-an-array-from-a-controller-duplicateInvolucre
D
7

You can use dependency injection in your controller method to get access to the needed objects.

<?php
namespace App\Http\Controllers;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Console\Kernel;

class MyController extends Controller {
    public function index(Kernel $kernel, Schedule $schedule)
    {
        dd($schedule->events());
    }
}

Note the Kernel instance is not used, but is required to be passed.

Dewees answered 22/2, 2016 at 17:27 Comment(7)
Thanks seems to be on the right sort of track. However the events it returns (Illuminate\Console\Scheduling\Event) don't seem to have access to the parent Command class that would contain $name, $description etc. Is there a way to get this?Unattended
No you wouldn't be able to get that because Laravel executes it as a new command by running php artisan [COMMAND] it doesn't call any of the internals strangely. You might be better off having a shared config with all the data you need which you can read into your schedule method and controller seperately.Dewees
That's not a bad idea, putting it all into a config file, then just calling it from within the kernel.phpUnattended
Just realised that this seems to give a duplicate array with each scheduled item being listed twice, is there a reason for this? I can't see what it's happening trying to go through the Artisan codeUnattended
you must be adding it twice in your schedule method somehow ;-)Dewees
Literally copied exactly what you have into a controllerUnattended
Was seeing the same behaviour as the OP with 2 instances of each event. Running Kernel::schedule() is not necessary as the kernel seems to schedule tasks automatically even when running in a web app.Calista
K
6

In Laravel Framework 8.22.1 I got to work by making app/Console/Kernel->schedule method public and then in a Controller:

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Events\Dispatcher;

    private function getScheduledJobs()
    {
        new \App\Console\Kernel(app(), new Dispatcher());
        $schedule = app(Schedule::class);
        $scheduledCommands = collect($schedule->events());

        return $scheduledCommands;
    }
Kozak answered 24/1, 2021 at 8:52 Comment(1)
You shouldn't need to change visibility on a method you aren't using in your code.Calista
S
1

I was having the task to stop/enable and edit the frequency of the scheduled tasks from the admin dashboard. So I foreach them in Kernel.php and capture the output in function.

$enabled_commands = ConsoleCommand::where('is_enabled', 1)
        ->get();

    foreach ($enabled_commands as $command)
    {
        $schedule->command($command->command_name)
            ->{$command->frequency}($command->time)
            ->after(function () use ($command) {
                $this->log($command->command_name);
            });
    }

Hope this help you.

Spoonfeed answered 22/7, 2016 at 14:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.