PHP LogoAsynchronous Programming

Asynchronous Programming (Asenkron Programlama) is a paradigm that allows a program to execute a long-running operation without blocking the main program execution thread. Instead of waiting for a task to complete before moving on to the next, the program can initiate a task and continue with other work. When the asynchronous task finishes, it notifies the program (e.g., via a callback, Promise, or Future), and the program can then process its result.

Key Concepts:
* Non-blocking I/O: This is the core idea. Instead of waiting for an I/O operation (like reading a file, making a network request, or querying a database) to complete, the system initiates the operation and immediately returns control to the program. The program can then do other work.
* Event Loop: Many asynchronous systems use an event loop, which continuously checks for events (like I/O completion, timers expiring, or new data arriving) and dispatches them to appropriate handlers (callbacks).
* Callbacks: Functions that are passed as arguments to other functions and are executed when the asynchronous operation completes.
* Promises/Futures: Objects that represent the eventual result of an asynchronous operation. They can be in a 'pending', 'fulfilled' (resolved successfully), or 'rejected' (failed) state. They provide a cleaner way to handle results and errors than deeply nested callbacks (callback hell).
* Async/Await (Fibers): Modern asynchronous patterns often use keywords like `async` to define functions that can run asynchronously and `await` to pause an `async` function's execution until a Promise/Future resolves, without blocking the entire program thread. PHP 8.1 introduced Fibers, which are lightweight, user-space threads, enabling this `async`/`await`-like syntax with libraries like Amp or Swoole Coroutines.

Why use Asynchronous Programming?
1. Responsiveness: Prevents the application from freezing or becoming unresponsive during long-running tasks, especially in user interfaces or web servers.
2. Efficiency and Throughput: Allows the program to handle multiple I/O-bound tasks concurrently. While waiting for one network request, it can initiate and process others, significantly improving the overall throughput of servers and applications.
3. Resource Utilization: Better utilizes CPU time by not idling while waiting for I/O operations.

Asynchronous Programming in PHP:
Traditionally, PHP is a synchronous, shared-nothing language, meaning each request typically runs in isolation, executes synchronously, and then terminates. However, with the rise of long-running PHP processes (e.g., web sockets, queue workers, microservices), asynchronous capabilities have become essential.

PHP achieves asynchronicity primarily through:
* Event Loop Libraries: Libraries like [ReactPHP](https://reactphp.org/) and [Amp](https://amphp.org/) provide an event loop and non-blocking I/O components, allowing PHP applications to handle multiple concurrent operations.
* Swoole/RoadRunner: These are high-performance PHP application servers that provide native coroutine support (a form of asynchronous execution) and persistent processes, making asynchronous programming very efficient.
* Fibers (PHP 8.1+): Native Fibers allow developers to write cooperative multitasking code directly in PHP, enabling `async`/`await` patterns with less boilerplate. Libraries like Amp leverage Fibers for their modern API.

Example Code

<?php

require 'vendor/autoload.php'; // Make sure to run `composer require amphp/http-client amphp/loop`

use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use function Amp\async;
use function Amp\delay;
use function Amp\Future\await;

echo "Program started synchronously.\n";

/
 * Defines an asynchronous operation to fetch a URL.
 * Returns an Amp\Future object that will eventually resolve with the HTTP status.
 * Requires PHP 8.1+ for underlying Fibers used by Amp's `async` and `await`.
 */
$fetchUrl = function (string $url, string $label): \Amp\Future {
    return async(function () use ($url, $label) {
        echo "[$label] Starting request to $url...\n";
        $httpClient = HttpClientBuilder::buildDefault();
        / @var Response $response */
        $response = await($httpClient->request(new Request($url)));
        echo "[$label] Received response from $url with status: " . $response->getStatus() . ".\n";
        return $response->getStatus();
    });
};

// Start multiple asynchronous HTTP requests concurrently
$future1 = $fetchUrl('https://www.example.com', 'Task 1');
$future2 = $fetchUrl('https://api.github.com/zen', 'Task 2'); // A simpler, faster API endpoint

// Simulate some synchronous work that could be done while requests are in flight.
// Note: `usleep` is a blocking call and will pause the entire script for 0.1 seconds.
echo "Main thread: Doing some other synchronous work...\n";
usleep(100000); // 0.1 seconds blocking delay
echo "Main thread: Finished other synchronous work (0.1s blocking).\n";

// Simulate some non-blocking work using Amp's `delay` function.
// `delay` returns a Future that resolves after the specified time, without blocking the event loop.
echo "Main thread: Scheduling a non-blocking delay...\n";
$delayFuture = delay(0.5); // 0.5 seconds non-blocking delay
// We explicitly `await` this future to ensure it completes, but during its 'wait' period,
// other async tasks (like HTTP requests) can continue making progress.
await($delayFuture);
echo "Main thread: Non-blocking delay finished (0.5s total async wait).\n";

// Await all previously started futures. This will block the program until all awaited futures are resolved.
// Since the HTTP requests were started *before* this await call, they might have already made progress or completed.
[$status1, $status2] = await([$future1, $future2]);

echo "All asynchronous operations completed.\n";
echo "Example.com status: {$status1}\n";
echo "Github API status: {$status2}\n";

echo "Program finished synchronously.\n";

/*
To run this code:
1. Ensure you have PHP 8.1 or higher.
2. Create a `composer.json` file:
   {
       "require": {
           "amphp/http-client": "^4.0",
           "amphp/loop": "^2.0"
       }
   }
3. Run `composer install` in your project directory.
4. Execute the script: `php your_script_name.php`

Expected output (order of lines may vary due to concurrency, showing non-blocking behavior):
Program started synchronously.
[Task 1] Starting request to https://www.example.com...
[Task 2] Starting request to https://api.github.com/zen...
Main thread: Doing some other synchronous work...
Main thread: Finished other synchronous work (0.1s blocking).
Main thread: Scheduling a non-blocking delay...
[Task 2] Received response from https://api.github.com/zen with status: 200.
[Task 1] Received response from https://www.example.com with status: 200.
Main thread: Non-blocking delay finished (0.5s total async wait).
All asynchronous operations completed.
Example.com status: 200
Github API status: 200
Program finished synchronously.
*/