Яндекс.Метрика

    Веб разработка

    Запланированная отправка постов (php, mongo, cron, regexp)

    Добрый день.

    Недавно мне пришлось писать страницу отправки постов на стены социальных сетей. Была поставлена задача постить на стену в определенное время а не сразу.

    Я написал страницу с полями для выбора соц сетей, текстом сообщения и самим полем для ввода времени отправки. Кроме обычного календаря с выбором даты и времени отправки, я добавил еще одно поле с вводом критерия отправки по правилу cron.

    Шаблон * * * * *

    После этого встал вопрос — как получить только нужные поля для отправки?
    Cron срабатывает каждую минуту и вызывает скрипт отправки постов, и перебирать каждую минуту всю таблицу подготовленных для отправки постов и сравниать с текущей датой/временем было бы лишней операцией.

    Я использую базу данных MongoDB, которая может выбирать все поля по регулярному выражению. Вот что я сделал:

    Берем текущую дату и время и переводим в массив

    $dateTime = explode(' ', date('i G j n w', time()));

    Далее строим регулярное выражение, которое выбирает записи, подходящие для отправки на текущий момент (текущая минута).

    $joe_search = new \MongoRegex(
    '/^(\*|((\d{1,2}\,)|(\*\/))*('.($dateTime[0]*1).'){1}(\,\d{1,2})*)\s'.
    '(\*|((\d{1,2}\,)|(\*\/))*('.($dateTime[1]).'){1}(\,\d{1,2})*)\s'.
    '(\*|((\d{1,2}\,)|(\*\/))*('.($dateTime[2]).'){1}(\,\d{1,2})*)\s'.
    '(\*|((\d{1,2}\,)|(\*\/))*('.($dateTime[3]).'){1}(\,\d{1,2})*)\s'.
    '(\*|(([1-6]{1}\,)|(\*\/))*('.($dateTime[4]).'){1}(\,[1-6]{1})*)$/i'
    ));

    $cursor = $collection->find(array("sendRule" => $joe_search));

    sendRule — название поля в базе, которое содержит наше cron правило.
    $dateTime[0] (минуты) могут быть с нулями в начале (например 05 минут), по этому мы умножаем их на 1 что бы убрать ноль.

    Тестировал * 1,12,20 7,8,12 * */3 (каждую минуту 1,12 и 20 часа 7,8,12 числа каждого месяца в среду).

    Вот собственно и все, далее циклом обрабатываем полученный массив и отправляем все что нужно.