Речь пойдет не о выполнении кода в потоке одного скрипта с таймаутами, а о задаче очередности некоего стека php кода в рамках некоего проекта с исполнением по таймаутам. Предположим есть некая строка в бд, которой необходимо проставить некий статус на заданное количество секунд и затем вернуть статусы на место. Напишем класс с функциями установки кода в стек, удаления кода из стека и выполнения кода по истечению таймаута. Код будем записывать в json файл, ключами массива сделаем microtime меточку и будем выполнять через eval вышедший по таймауту код:
<?php class Phpstack { public static $filename = 'phpstack.json'; public static function set($code, $time) { $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); $key = microtime(true) + $time; while (isset($arr[$key])) { $key = $key + 0.0001; } $key = (string)$key; $arr[$key] = $code; $file->ftruncate(0); $file->fwrite(json_encode($arr)); $file->flock(LOCK_UN); return $key; } public static function remove($key) { $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); if (isset($arr[$key])) { unset($arr[$key]); } $file->ftruncate(0); $file->fwrite(json_encode($arr)); $file->flock(LOCK_UN); } public static function execute() { global $mysqli; $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); $exec = false; foreach ($arr as $key => $value) { if ($key <= microtime(true)) { eval($value); unset($arr[$key]); $exec = true; } } if ($exec) { $file->ftruncate(0); $file->fwrite(json_encode($arr)); } $file->flock(LOCK_UN); } }
Функция set принимает в аргументах строку кода и таймаут в секундах, через который он должен быть исполнен. Возвращает установленный ключ — для того чтобы код можно было в случае чего удалить без исполнения по данному ключу функцией remove. Функция execute исполняет вышедший из заданного таймаута стек кодов. Блокировкой файла мы исключаем возможность повторного исполнения одного и того же кода.
Использование, добавляем код в стек на 122 секунды:
$mysqli->query("UPDATE `questions` SET `section` = 12, `app_status` = 14 WHERE `id` = $id"); Phpstack::set('$mysqli->query("UPDATE `questions` SET `section` = 7, `app_status` = 2 WHERE `id` = ' . $id . '");', 122);
А в индексном файле проекта пропишем исполнение:
Phpstack::execute();
глобальную $mysqli добавил потому что она требуется в текущем проекте для запроса в бд, у вас же её может не быть.
UPD: обновил код и добавил функцию executeKey($key)
Функция нужна для того, чтобы вызвать по ключу(ключ возвращается функцией set) код прямо здесь и сейчас(без учета таймаута). Т.е. функция remove просто удаляет заданный код по ключу, без выполнения, а функция executeKey выполняет и удаляет код.
<?php class Phpstack { public static $filename = 'phpstack.json'; public static function set($code, $time) { $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); $key = microtime(true) + $time; while (isset($arr[$key])) { $key = $key + 0.0001; } $key = (string)$key; $arr[$key] = $code; $file->ftruncate(0); $file->fwrite(json_encode($arr)); $file->flock(LOCK_UN); return $key; } public static function remove($key) { $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); if (isset($arr[$key])) { unset($arr[$key]); } $file->ftruncate(0); $file->fwrite(json_encode($arr)); $file->flock(LOCK_UN); } public static function execute() { global $mysqli; $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); $exec = false; foreach ($arr as $key => $value) { if ($key <= microtime(true)) { eval($value); unset($arr[$key]); $exec = true; } } if ($exec) { $file->ftruncate(0); $file->fwrite(json_encode($arr)); } $file->flock(LOCK_UN); } public static function executeKey($key) { global $mysqli; $file = new SplFileObject(self::$filename, 'a+b'); $file->flock(LOCK_EX); $file->rewind(); $data = $file->fread($file->getSize()); $data = $data ?: '[]'; $arr = json_decode($data, true); if (isset($arr[$key])) { eval($arr[$key]); unset($arr[$key]); } $file->ftruncate(0); $file->fwrite(json_encode($arr)); $file->flock(LOCK_UN); } }