Задать вопрос

Как php (в частности на Laravel) сайты осуществляют события при наступлении нужных даты/времени?

Здравствуйте!
Понадобилась сейчас реализовать выполнение многих разных задач при наступлении определённых даты/времени (у каждой задачи прописаны эти дата/время) на сайте.
1 тип событий: Пользователи могут включать какие-то события, т.е. жмут кнопку, сервер производит какие-то действия, расчёты, обновляет данные в бд (postgresql) ставя в них дату/время начала и расчитанные дату/время окончания для этого события и этого юзера.
2 тип событий: Уже есть заготовленные события, которые вызываются в определённое время, напр. каждый вторник в 15:15 всем юзерам выдать такое-то сообщение, или определённые данные в бд обновить или ещё что.
Нужно: отслеживать, подошли ли дата/время этих событий; когда подошли - вызвать соответствующий событию метод, обновить данные в бд, если нужно - выдать уведомления одному или нескольким юзерам или запустить ещё какое-то событие, так же отслеживаемое.
Т.е., как я это вижу пока, каждую секунду (либо минуту, пока ещё не решено длительность задач будет кратна секунде или минуте) нужно проверять весь список имеющихся задач и сравнивать их дату/время с наступившим временем на сервере. Если совпало, то выполнить эту задачу.

Как такое реализовывают на сайтах php, в частности на Laravel?
Мне посоветовали очереди с redis, прочитала, но вроде они не позволяют выполнять задачи по времени, а просто одну за другой выполняют. Или это не так и можно настроить их по времени? А если нет, что тогда подходит для решения данного случая? В ларе ещё events есть, может это то, что нужно? Подскажите, пожалуйста. сталкиваюсь с подобным впервые..
Использую Laravel 5.4, postgresql 11.1, xampp - php 7.2.0, apache 2.4.29, windows 10, не продакш, у себя локально делаю.
  • Вопрос задан
  • 3011 просмотров
Подписаться 5 Простой Комментировать
Решения вопроса 5
@EvgeniiR
https://github.com/EvgeniiR
Легко )
Стартуют команды Cron'ом
Ответ написан
@Barmunk
Настройте Laravel Task Scheduler на винде и используйте внутренний планировщик, как описано в документации.

Как включить Task Scheduler на win10 https://quantizd.com/how-to-use-laravel-task-sched...
Ответ написан
Комментировать
Helldar
@Helldar
Just do it.
Используйте шедулер https://laravel.com/docs/5.8/scheduling
В случае юзерских, выполняя команду https://laravel.com/docs/5.8/artisan пробегаете по юзерам и смотрите у кого "наступило время".
Если точнее, выставить запрос, исключающий лишнее. Например,

$items = App\Page::where('available_at', '<=', now())->get();

Про редиску выше писали - это очереди, там совсем другое и не про то (https://laravel.com/docs/5.8/queues)
Ответ написан
Комментировать
Alixx
@Alixx Автор вопроса
Всем спасибо за ответы.) Всё получилось с планировщиком задач в ларе и винде. Может кому пригодится, опишу подробней:
В бд создать таблицу с задачами (id, date_end с индексом - не позже этого времени нужно выполнить эту задачу, type - тип задачи, и пр.).
В app/Console/Kernel.php создала artisan команду, вызывается ежеминутно
...
 protected $commands = [
        'App\Console\Commands\DateTasksUsers'
    ];
 protected function schedule(Schedule $schedule)
    {
        $schedule->command('date_tasks:users')->everyMinute();
    }
...

В app/Console/Commands/DateTasksUsers.php - файл для команды. В ней проходим таблицу задач, ищем те, время которых уже подошло. Для каждой полученной задачи вызываем соответствующую функцию.
...
    protected $signature = 'date_tasks:users';
    ...  
    public function handle()
    {
        $tasks = TaskUser::where('date_end', '<=', time())
            ->get(); 
        if (!is_null($tasks)) {
            foreach($tasks as $task)
            {
                if ($task->type == 1)
                    User::task_change($task); // там уже проверяем данные, обновляем данные в бд, уведомление кидаем 
                                    // юзеру и т.д. Там же в конце удаляем эту задачу.
                elseif ($task->type == 2)
                    Item::task_upgrade($task);
                // дальше так же добавлять новые типы задач и вызов соответствующих ф-й для них
            }
        }
    }

Настроить планировщик винды (у меня 10ка) как в статье (там для xampp как раз показано), которую скинул Barmunk.
Вот и все манипуляции)
Смущает только то, что задачи выполняются последовательно, а надо бы запустить их все разом параллельно, т.е. в несколько процессов.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 4
Не могу сказать точно, что поняла суть вопроса, но если речь идёт о событиях в определённое время, то можно использовать такой вариант:

Вместо проверки точной даты и времени
( " if ($date == ... ) " )
нужно использовать, чтобы дата проверялась как-бы "поверх" нужного значения

То есть, задана, например, дата выполнения задачи 15 сентября в 6:00.
В MySQL записываем это DATETIME вместе, либо в отдельной ячейке год, отдельно час и так далее

Как только Пользователь заходит на сайт, мы сверяем не дату с датой, а если месяц больше указанного месяца, если год больше указанного года и так далее:

// Получаем текущую дату
$Y = date("Y");
$m = date("m");
$d = date("d");

// Из запроса MySQL Select берём дату мероприятия
$event_year = $myrow['year'];
...

if ($event_year < $Y || $event_month < $m || $event_day < $d) {
echo 'Событие "Капитаны" уже проводится/проводилось';
}


Если Вы записывали в MySQL дату целиком, то всё то-же самое, только обрезаем её

$event_date = $myrow['date'];
            
$event_year = substr($event_date, 0, 4);
$event_month = substr($event_date, 5, 2);
$event_day = substr($event_date, 8, 2);


Это НЕ работает:
Если надо высылать уведомление о начале события на Емейл и подобное.

Когда Пользователь заходит на сайт, тогда идёт проверка, но при этом событие появляется.
Чуть покопавшись, можно так-же сделать и конец события
Ответ написан
@potkot
PHP программист
Из комментов понял, что у вас не Linux сервер. Если так, то в windows есть планировщик заданий (и в сервер версии и в обычной). Это то же самое, что крон по факту. Запускает задачи в определенное время с определенной переодичностью.
Ответ написан
Комментировать
@Imrahil
Ну или не тянуть в крон Лару, а воспользоваться например готовым
https://github.com/hutnikau/job-scheduler
Или
https://m.habr.com/ru/post/345802
Ответ написан
Комментировать
xPomaHx
@xPomaHx
1vs9
Если вопрос "как?" теоретический, то вордпрес например имеет свой крон, и на каждый запрос проверяет нужно ли че нибудь запустить, то есть если у вас задача на ночь, а человек тока утром зайдет на главную страницу, то и задача утром запустится.
Такое не сложно и на ларе реализовать если уже не сделано чего то готового.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы