lumetas / luper
Requires
- php: ^8.1
- opis/closure: ^4.3
This package is not auto-updated.
Last update: 2025-09-07 17:48:00 UTC
README
Введение
О библиотеке
Luper - это легковесная библиотека для асинхронного программирования в PHP, предоставляющая механизмы для работы с параллельными задачами, таймерами и файберами.
Ключевые возможности
Асинхронное выполнение PHP-функций через отдельные процессы
Управление задачами с помощью Fibers (доступно с PHP 8.1)
Таймеры и периодические задачи
Неблокирующее ожидание результатов
Простой и интуитивно понятный API
Установка
Требования
PHP >= 8.1
Composer
composer require lumetas/luper
Основные компоненты
Async - Асинхронное выполнение
Класс для запуска PHP-функций в отдельных процессах.
Создание асинхронной задачи
<?php use Luper\Async; // Создание асинхронной функции из файла $asyncFunction = Async::create(__DIR__.'/my_function.php');
Запуск и ожидание результата
<?php // Запуск с аргументами $promise = $asyncFunction("arg1", "arg2"); // Проверка завершения if ($promise->isCompleted()) { $result = $promise->getResult(); } // Получение ошибки (если есть) $error = $promise->getError();
Loop - Цикл событий
Центральный класс для управления асинхронными задачами.
Создание экземпляра
<?php use Luper\Loop; // Создание нового цикла $loop = new Loop(); // Или использование синглтона $loop = Loop::make();
Добавление задач
<?php $loop->addTask(function () { // Ваш код здесь echo "Выполнено в файбере!"; });
Таймеры
<?php // Одноразовый таймер $timerId = $loop->addTimer(2.5, function () { echo "Выполнится через 2.5 секунды"; }); // Периодический таймер $repeatingTimerId = $loop->addTimer(1.0, function () { echo "Выполняется каждую секунду"; }, true); // Отмена таймера $loop->clearTimer($timerId);
Управление выполнением
<?php // Запуск цикла $loop->run(); // Остановка цикла $loop->stop(); // Приостановка выполнения в файбере Loop::suspend(); // Задержка выполнения $loop->sleep(0.5); // sleep на 0.5 секунды
Пример использования
Базовый пример
<?php require_once "vendor/autoload.php"; use Luper\Async; use Luper\Loop; $startTime = time(); function createRequests($count) { $loop = new Loop(); $results = []; for($i = 0; $i < $count; $i++) { $loop->addTask(function () use (&$loop, &$results) { $asyncFunc = Async::create(__DIR__.'/requestFunc.php'); $promise = $asyncFunc("https://google.com"); while ($promise->getResult() === null) { $loop->suspend(); } $results[] = strlen($promise->getResult()['result']); }); } $loop->run(); return $results; } var_dump(createRequests(10)); echo "\nИтоговое время: " . (time() - $startTime);
Пример файла requestFunc.php
<?php // Файл должен возвращать callable функцию return function($url) { // Имитация HTTP-запроса sleep(1); // Длительная операция return [ 'status' => 200, 'content' => file_get_contents($url), 'headers' => [] ]; };
Практические примеры
Параллельные HTTP-запросы
<?php use Luper\Async; use Luper\Loop; function fetchMultipleUrls(array $urls) { $loop = new Loop(); $responses = []; foreach ($urls as $index => $url) { $loop->addTask(function () use ($url, $index, &$responses, $loop) { $fetch = Async::create(__DIR__.'/fetch_url.php'); $promise = $fetch($url); while (!$promise->isCompleted()) { Loop::suspend(); } $responses[$index] = $promise->getResult(); }); } $loop->run(); return $responses; }
Периодические задачи
<?php use Luper\Loop; $loop = new Loop(); // Обновление кэша каждые 30 секунд $loop->addTimer(30, function () { updateCache(); }, true); // Одноразовая задача через 5 секунд $loop->addTimer(5, function () { sendNotification(); }); $loop->run();
Pull и PullMax
Это два класса представляющие собой обёртку над функционалом. Чтобы было проще обрабатывать данные Пример:
<?php use Luper\Pull; $items = []; for($i = 0; count($items) < 50; $i ++) {$items[] = $i;} $pullSize = 10; // Создаем пул с максимум 3 параллельными процессами $pull = new Pull($pullSize, __DIR__.'/proc.php'); // Добавляем задачи foreach ($items as $item) { $pull->add($item, 'дополнительный_аргумент'); } // Запускаем обработку $results = $pull->run();
И аналогичный пример для PullMax:
<?php use Luper\PullMax; $items = []; for($i = 0; count($items) < 50; $i ++) {$items[] = $i;} $pullSize = 10; $pull = new PullMax(__DIR__.'/proc.php'); // Добавляем задачи foreach ($items as $item) { $pull->add($item, 'дополнительный_аргумент'); } // Запускаем обработку $results = $pull->run();
Класс Pull Позволяет легко обрабатывать данные, указав максимальное количество одновременно запущенных процессов. PullMax Будет пытаться запустить столько паралельных процессов сколько сможет
await
Асинхронная функция при выполнении возвращает промис, у которого есть метод await, он возвращает результат работы функции, если функция ещё не выполнена метод останавливает поток выполнения дожидаясь завершения, в случае если метод был вызван внутри файбера, то файбер будет приостанавливаться до завершения выполнения функции. Поэтому метод крайне полезно использовать внутри EventLoop, пример:
<?php use Luper\{Loop, Async}; $func = Async::create(__DIR__.'/proc.php'); $loop = new Loop; $results = []; foreach ($elems as $elem) { $loop->addTask(function () use ($func, $loop, &$results) { $results[] = $func(1, 2)->await(); }); } $loop->run(); var_dump($results);
Best Practices
Структура асинхронных функций
- Каждая асинхронная функция должна быть в отдельном файле
- Файл должен возвращать callable
- Используйте обработку ошибок внутри функций
Управление памятью
- Используйте ссылки для больших данных чтобы избежать копирования
Производительность
- Не создавайте чрезмерное количество параллельных процессов
Ограничения
- Ограничения процессов PHP (память, время выполнения)
- Требует аккуратного управления ресурсами
Заключение
Luper предоставляет простой и эффективный способ асинхронного программирования в PHP, особенно полезный для I/O-операций и параллельной обработки задач.