问题
I need to create a cron job that will run every minute and search a mysql database for all rows that have a date field that is equal to the current date and time rounded to the minute.
My problem is what is the proper query and perhaps the best way to store the event date.
The basic use case here is that I have scheduled events and I need to send a notification at the exact time those events were scheduled. This seems like a pretty common thing to do but I am having trouble figuring out if this is the best approach.
Thanks in advance.
回答1:
Create an artisan command for your scheduler:
file: app/commands/CheckSchedule.php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class CheckScheduleCommand extends Command {
/**
* The console command name.
*
* @var string
*/
protected $name = 'check:schedule';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Process scheduled messages.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(Scheduler $scheduler)
{
parent::__construct();
$this->scheduler = $scheduler;
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$this->scheduler->check();
}
}
Tell Artisan to load your command editing file app\start\artisan.php and adding:
Artisan::resolve('CheckScheduleCommand');
Create a Scheduler class:
class Scheduler {
public function check()
{
$date = \Carbon\Carbon::now();
// set the seconds to 59 to get the 'whole' minute in the
$date->second = 59;
/// this filter will get every notification not sent from now to the past
/// If your server got slow or something like that people will still be notified
$notifications = Schedule::where('notify_at','<=',$date)->where('notified',false)->get();
foreach($notifications as $notification)
{
$this->notify($notification);
}
}
public function notify($notification)
{
/// do whatever you need here to notify your user;
$notification->notified = true;
$notification->save();
}
}
Then test it by running
php artisan check:schedule
And you can use cron to do it every minute
* * * * * /path/to/php /var/www/project/artisan check:schedule
About your date field, you better use a timestamp, will be easier to filter and you can use acessors and mutators to make people use it friendly and still store it as timestamp: http://laravel.com/docs/eloquent#accessors-and-mutators
回答2:
maybe you need to change the logic a little bit.
you can make it much more easier, just implement this chunk of query:
... WHERE date_field <= CURRENT_TIMESTAMP() AND processed = 0;
note that I have used CURRENT_TIMESTAMP() function, its because of query speed, if you store date as an unix timestamp in INTEGER type field, it will be very fast
来源:https://stackoverflow.com/questions/19304071/select-all-rows-with-a-date-of-right-now