# Async PHP Patterns ## Swoole HTTP Server ```php set([ 'worker_num' => 4, 'max_request' => 10000, 'task_worker_num' => 2, 'enable_coroutine' => true, ]); $server->on('start', function (Server $server) { echo "Swoole HTTP server started at http://0.0.0.0:9501\n"; }); $server->on('request', function (Request $request, Response $response) { $response->header('Content-Type', 'application/json'); match ($request->server['request_uri']) { '/api/users' => handleUsers($request, $response), '/api/health' => $response->end(json_encode(['status' => 'healthy'])), default => $response->status(404)->end(json_encode(['error' => 'Not found'])), }; }); function handleUsers(Request $request, Response $response): void { // Coroutine for concurrent DB queries go(function () use ($response) { $users = queryDatabase('SELECT * FROM users LIMIT 10'); $response->end(json_encode(['data' => $users])); }); } $server->start(); ``` ## Swoole Coroutines ```php add(); go(function () use ($url, &$results, $wg) { $client = new Client(parse_url($url, PHP_URL_HOST), 443, true); $client->set(['timeout' => 5]); $client->get(parse_url($url, PHP_URL_PATH)); $results[$url] = [ 'status' => $client->statusCode, 'body' => $client->body, ]; $client->close(); $wg->done(); }); } $wg->wait(); print_r($results); }); ``` ## Swoole Async MySQL ```php connect([ 'host' => '127.0.0.1', 'port' => 3306, 'user' => 'root', 'password' => 'password', 'database' => 'test', ]); if (!$connected) { throw new \RuntimeException($mysql->connect_error); } // Async query $result = $mysql->query('SELECT * FROM users WHERE active = 1'); foreach ($result as $row) { echo "User: {$row['name']}\n"; } // Prepared statements $stmt = $mysql->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([42]); $user = $stmt->fetchAll(); $mysql->close(); }); ``` ## Swoole Channel (Communication) ```php push("Task {$i}"); echo "Produced: Task {$i}\n"; Coroutine::sleep(0.5); } $channel->close(); }); // Consumer go(function () use ($channel) { while (true) { $task = $channel->pop(); if ($task === false && $channel->errCode === SWOOLE_CHANNEL_CLOSED) { break; } echo "Consumed: {$task}\n"; Coroutine::sleep(1); } }); }); ``` ## ReactPHP Event Loop ```php 'application/json'], json_encode([ 'method' => $request->getMethod(), 'uri' => (string) $request->getUri(), 'timestamp' => time(), ]) ); }); $socket = new React\Socket\SocketServer('0.0.0.0:8080'); $server->listen($socket); echo "Server running at http://0.0.0.0:8080\n"; // Periodic timer Loop::addPeriodicTimer(5.0, function () { echo "Heartbeat: " . date('H:i:s') . "\n"; }); // One-time timer Loop::addTimer(10.0, function () { echo "This runs once after 10 seconds\n"; }); ``` ## ReactPHP Async MySQL ```php createLazyConnection('root:password@localhost/database'); $connection->query('SELECT * FROM users WHERE active = 1') ->then( function (QueryResult $result) { echo "Found " . count($result->resultRows) . " users\n"; foreach ($result->resultRows as $row) { echo "User: {$row['name']}\n"; } }, function (\Exception $error) { echo "Error: " . $error->getMessage() . "\n"; } ); // Prepared statements $connection->query('SELECT * FROM users WHERE id = ?', [42]) ->then(function (QueryResult $result) { $user = $result->resultRows[0] ?? null; var_dump($user); }); ``` ## ReactPHP Promises ```php resolve([ 'id' => $id, 'name' => "User {$id}", ]); }); return $deferred->promise(); } // Using promises fetchUser(42) ->then(function ($user) { echo "Got user: {$user['name']}\n"; return fetchUserPosts($user['id']); }) ->then(function ($posts) { echo "Got " . count($posts) . " posts\n"; }) ->catch(function (\Exception $error) { echo "Error: " . $error->getMessage() . "\n"; }); // Parallel promises all([ fetchUser(1), fetchUser(2), fetchUser(3), ])->then(function ($users) { echo "Fetched " . count($users) . " users\n"; }); ``` ## PHP Fibers (Native PHP 8.1+) ```php isStarted()) { return $fiber->start(); } if ($fiber->isTerminated()) { return $fiber->getReturn(); } return $fiber->resume(); } // Simulate async I/O function fetchData(string $url): Fiber { return async(function () use ($url) { echo "Fetching: {$url}\n"; Fiber::suspend('pending'); // Simulate network delay sleep(1); return "Data from {$url}"; }); } // Usage $fiber1 = fetchData('https://api.example.com/users'); $fiber2 = fetchData('https://api.example.com/posts'); await($fiber1); await($fiber2); $result1 = await($fiber1); $result2 = await($fiber2); echo "{$result1}\n"; echo "{$result2}\n"; ``` ## Amphp Framework ```php addRoute('GET', '/api/users', function (Request $request): Response { // Concurrent database queries $users = await([ async(fn() => queryUsers()), async(fn() => queryUserStats()), ]); return new Response( status: 200, headers: ['content-type' => 'application/json'], body: json_encode(['users' => $users[0], 'stats' => $users[1]]), ); }); $server = new HttpServer( servers: [SocketServer::listen('0.0.0.0:8080')], requestHandler: $router, ); $server->start(); ``` ## Quick Reference | Technology | Use Case | Performance | |------------|----------|-------------| | Swoole | High-performance servers, WebSockets | Very High | | ReactPHP | Event-driven apps, real-time | High | | Amphp | Modern async framework | High | | Fibers | Native async (PHP 8.1+) | Medium | | Generators | Simple async patterns | Medium | | Feature | Swoole | ReactPHP | Amphp | |---------|--------|----------|-------| | Coroutines | Yes | No (Promises) | Yes (Fibers) | | HTTP Server | Built-in | Via package | Via package | | WebSockets | Built-in | Via package | Via package | | Extension | Required | Not required | Not required | | Learning Curve | Medium | Low | Medium |