Асинхронное программирование в PHP: полное руководство для начинающих

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в асинхронное программирование в PHP

Традиционно PHP работает в синхронном режиме: каждый запрос выполняется последовательно, строка за строкой. Однако в современной веб-разработке всё чаще требуется обрабатывать множество задач одновременно — от отправки писем до работы с WebSocket и API. Асинхронное программирование в PHP позволяет решать эти задачи эффективно, не блокируя основной поток выполнения.

В этом руководстве мы разберём, что такое асинхронность, зачем она нужна, и как начать её использовать в PHP. Вы узнаете о ключевых инструментах: Fiber, ReactPHP, Swoole и встроенных функциях для работы с корутинами.

Что такое асинхронное программирование и зачем оно нужно?

Синхронный vs Асинхронный код

Представьте, что вы заказываете пиццу. Синхронный подход: вы звоните, ждёте, пока её приготовят, и только потом кладёте трубку. Асинхронный: вы звоните, оставляете заказ, а пока пиццу готовят — занимаетесь своими делами. В PHP это выглядит так:

// Синхронный код (блокирующий)
$data = file_get_contents('https://api.example.com');
echo "Данные получены: " . $data; // Ждём, пока загрузится

// Асинхронный код (неблокирующий)
$promise = async_file_get_contents('https://api.example.com');
echo "Запрос отправлен, можно делать другие дела...";
$data = await($promise); // Получаем результат позже

Проблемы синхронного PHP

  • Блокировка I/O: операции с файлами, БД или сетевыми запросами останавливают выполнение скрипта
  • Низкая производительность: каждый новый запрос требует отдельного процесса или потока
  • Проблемы с реальным временем: чаты, уведомления и стриминг работают неэффективно

Преимущества асинхронного подхода

  • Одновременная обработка сотен и тысяч соединений
  • Экономия памяти и ресурсов сервера
  • Возможность создавать real-time приложения
  • Более отзывчивые интерфейсы

Основные инструменты асинхронного PHP

1. Корутины и Fiber (PHP 8.1+)

Начиная с PHP 8.1, появилась встроенная поддержка Fiber — легковесных корутин. Fiber позволяет приостанавливать выполнение функции и возобновлять её позже, не блокируя основной поток.

<?php
$fiber = new Fiber(function(): void {
    $value = Fiber::suspend('first');
    echo "Возобновлён со значением: $value\n";
});

$value = $fiber->start();
echo "Начальное значение: $value\n"; // first
$fiber->resume('second'); // Возобновлён со значением: second
?>

2. ReactPHP — Event Loop для PHP

ReactPHP — это библиотека, которая реализует событийно-ориентированное программирование (event loop). Она позволяет выполнять неблокирующие операции ввода-вывода.

<?php
require 'vendor/autoload.php';

$loop = React\EventLoop\Loop::get();

$loop->addTimer(1.0, function () {
    echo "Прошла 1 секунда\n";
});

$loop->addTimer(2.0, function () {
    echo "Прошло 2 секунды\n";
});

echo "Старт...\n";
$loop->run();
?>

ReactPHP также предоставляет асинхронные HTTP-клиенты и серверы:

<?php
$browser = new React\Http\Browser($loop);

$browser->get('https://api.example.com')->then(
    function (Psr\Http\Message\ResponseInterface $response) {
        echo "Ответ: " . $response->getBody();
    },
    function (Exception $e) {
        echo "Ошибка: " . $e->getMessage();
    }
);
?>

3. Swoole — высокопроизводительный асинхронный сервер

Swoole — это расширение для PHP, которое превращает его в полноценный асинхронный сервер. Оно поддерживает корутины, WebSocket, TCP/UDP серверы и многое другое.

<?php
// Простой HTTP-сервер на Swoole
$http = new Swoole\Http\Server("0.0.0.0", 9501);

$http->on("request", function ($request, $response) {
    $response->header("Content-Type", "text/plain");
    $response->end("Hello World\n");
});

$http->start();
?>

С корутинами Swoole код выглядит почти как синхронный, но работает асинхронно:

<?php
go(function () {
    // Асинхронный HTTP-запрос
    $data = Co::get('https://api.example.com');
    echo "Данные: " . $data;
});
?>

Практические примеры асинхронного кода

Пример 1: Асинхронная отправка email

Вместо того чтобы заставлять пользователя ждать, пока письмо отправится, используем ReactPHP:

<?php
use React\EventLoop\Loop;
use React\Promise\Deferred;

function sendEmailAsync(string $to, string $subject, string $body): React\Promise\PromiseInterface
{
    $deferred = new Deferred();
    
    // Имитация отправки через 2 секунды
    Loop::get()->addTimer(2.0, function () use ($deferred, $to) {
        echo "Письмо отправлено на $to\n";
        $deferred->resolve(true);
    });
    
    return $deferred->promise();
}

// Использование
echo "Начинаем отправку...\n";
sendEmailAsync('user@example.com', 'Привет', 'Тело письма')->then(function () {
    echo "Отправка завершена!\n";
});
echo "Пользователь может продолжать работу...\n";
?>

Пример 2: Параллельный парсинг нескольких сайтов

<?php
require 'vendor/autoload.php';

use React\Http\Browser;
use React\EventLoop\Loop;

$loop = Loop::get();
$browser = new Browser($loop);

$urls = [
    'https://example.com/page1',
    'https://example.com/page2',
    'https://example.com                

Блоги

Рекомендаций по книгам