amphp/amp
AMPHP (AMP) accelerates PHP concurrency with fibers, eliminating callbacks and generators. Built on PHP 8.1’s cooperative coroutines, it lets you run async tasks like sync code—ideal for I/O-bound apps. Use Amp\async() for parallel execution and Future::await() to handle results seamlessly. No event...
Installation:
composer require amphp/amp revolt/event-loop
Ensure PHP 8.1+ is used (fibers are required).
First Use Case: Replace blocking I/O with non-blocking alternatives. For example, fetch multiple URLs concurrently:
use Amp\async;
use Amp\Http\Client\HttpClientBuilder;
$httpClient = HttpClientBuilder::buildDefault();
$futures = [
async(fn() => $httpClient->request('https://example.com')),
async(fn() => $httpClient->request('https://google.com'))
];
$results = Amp\Future\await($futures);
Where to Look First:
Amp\async() for running coroutines.Amp\Future\await() for combining results.Concurrent HTTP Requests:
Use Amp\Future\await() to parallelize HTTP calls (e.g., with amphp/http-client):
$futures = array_map(
fn($url) => async(fn() => $httpClient->request($url)),
['url1', 'url2']
);
$responses = Amp\Future\await($futures);
Database Operations:
Offload blocking DB queries to fibers with amphp/mysql/amphp/postgres:
$results = Amp\Future\await([
async(fn() => $pdo->query('SELECT * FROM users')->fetchAll()),
async(fn() => $pdo->query('SELECT * FROM posts')->fetchAll())
]);
Event-Driven Pipelines:
Chain futures with map()/catch() for transformations:
$future = async(fn() => fetchData())
->map(fn($data) => processData($data))
->catch(fn($e) => logError($e));
Cancellation:
Pass a Cancellation token to futures for cooperative shutdown:
$cancellation = new Amp\Cancellation;
$future = async(fn() => longRunningTask(), $cancellation);
$cancellation->cancel(); // Terminates the task
Laravel Integration:
Use Amp\async() in Laravel’s service containers or queues:
public function handle(Job $job) {
$result = async(fn() => $job->process())->await();
}
Note: Avoid mixing synchronous Laravel code with Amp fibers (e.g., Eloquent ORM may block).
Reactive Streams:
Combine with amphp/byte-stream for async I/O:
$stream = async(fn() => $socket->read());
$data = $stream->await();
Parallel Processing:
Use amphp/parallel for CPU-bound tasks:
$results = Amp\Parallel\run(function() {
return computeHeavyTask();
});
Blocking Calls:
file_get_contents()) with fibers blocks the entire event loop.amphp/byte-stream, amphp/http-client).Fiber Leaks:
await() futures or use finally() to clean up:
$future->finally(fn() => $deferred->complete());
Cancellation Ignored:
$future->onCancel(fn() => $pdo->cancelQuery());
State Sharing:
Revolt\EventLoop::getSuspension()->debug() to trace fiber execution.$future->await(new Amp\TimeoutCancellation(1000)); // 1-second timeout
Custom Futures:
Extend Amp\Future for domain-specific logic:
class CustomFuture extends Amp\Future {
public function retry(int $attempts): self { ... }
}
Event Loop Hooks: Integrate with Revolt’s event loop for custom scheduling:
Revolt\EventLoop::onTick(fn() => $this->tickHandler());
Cancellation Strategies:
Implement Amp\CancellationAwareInterface for cooperative shutdowns:
class MyTask implements CancellationAwareInterface {
public function onCancel(): void { ... }
}
ext-event:
pecl install event
Fiber::setStackSize(4 * 1024 * 1024); // 4MB stack
awaitAll, awaitAny) to build reactive pipelines:
$results = Amp\Future\awaitAll([
async(fn() => $db->query('SELECT * FROM users')),
async(fn() => $cache->get('users'))
]);
DeferredFuture:
Prefer Amp\async() unless implementing low-level async primitives.Amp\Loop:
Use Amp\Loop::run() for isolated testing:
Amp\Loop::run(fn() => $this->testAsyncCode());
How can I help you explore Laravel packages today?