Issue
I'm wondering what the best way to add things like weekends to the available schedule constraints:
Illuminate\Console\Scheduling\Event.php
public function weekdays()
{
return $this->spliceIntoPosition(5, '1-5');
}
and its logical opposite:
public function weekends()
{
return $this->days(array( '0','6'));
}
Where would I include these things so that they're not overwritten with a framework update?
Solution
First of all, if all you are missing is the weekends() method, you can achieve that by calling days(6,7) on your event.
If you need to add some more logic to the scheduler, please go on reading.
I had a look at the code and while Laravel doesn't offer a way to extend the Scheduler, and specifically its scheduled Events, with additional methoods, it's still possible to apply additional constraints from your Kernel::schedule().
Depending on your needs, there are 2 ways to do it.
If you want to set some custom CRON expression for an event, you can simply use its cron() method:
protected function schedule(Schedule $schedule) { $schedule->call(function () { //scheduled code })->cron('0 1 2 * * *')->daily(); }
If you need to apply some CRON constraints using existing methods, but need to modify it later the way weekdays() does using spliceIntoPosition, you can access it by calling getExpression(), modify it, and then set using cron().
protected function schedule(Schedule $schedule) { $event = $schedule->call(function () { //scheduled code }); $scheduledAt = $event->getExpression(); //get cron expression ...; //modify the $scheduledAt expression $event->cron($scheduledAt); // set the new schedule for that even }
If you want to reuse the logic for multiple events, you can add helper functions in your Kernel.php, e.g.:
protected function specialSchedule(\Illuminate\Console\Scheduling\Event $event) {
$scheduledAt = $event->getExpression();
...; // modify $scheduledAt expression
$event->cron($scheduledAt);
return $event;
}
Then you can reuse that logic when defining the schedule:
protected function schedule(Schedule $schedule)
{
$this->specialSchedule($schedule->call(function () {
//scheduled code
}));
}
UPDATE:
There is one more way to do that - a bit more complex, as it requires you to provide your own Schedule and Event classes, but also more flexible.
First, implement your own Event class and add there the new methods:
class CustomEvent extends \Illuminate\Console\Scheduling\CallbackEvent {
public function weekends() {
return $this->days(6,7);
}
}
Then your own Schedule class, so that it creates CustomEvent objects:
class CustomSchedule extends \Illuminate\Console\Scheduling\Schedule
{
public function call($callback, array $parameters = [])
{
$this->events[] = $event = new CustomEvent($callback, $parameters);
return $event;
}
public function exec($command, array $parameters = [])
{
if (count($parameters)) {
$command .= ' '.$this->compileParameters($parameters);
}
$this->events[] = $event = new Event($command);
return $event;
}
}
Lastly, in your Kernel.php you need too make sure your new schedule class is used for scheduling:
protected function defineConsoleSchedule()
{
$this->app->instance(
'Illuminate\Console\Scheduling\Schedule', $schedule = new Schedule
);
$this->schedule($schedule);
}
Answered By - jedrzej.kurylo Answer Checked By - Katrina (WPSolving Volunteer)