PHP code example of jerome / fetch-php

1. Go to this page and download the library: Download jerome/fetch-php library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

jerome / fetch-php example snippets


use function Matrix\Support\async;

// JavaScript-like promise chaining in PHP
async(fn() => fetch('https://api.example.com/users'))
    ->then(fn ($response) => $response->json())
    ->catch(fn ($error) => echo "Error: " . $error->getMessage())
    ->finally(fn () => echo "Request completed.");

$handler = fetch_client()->getHandler();
$handler->async();

$handler->get('https://api.example.com/users')
    ->then(fn ($response) => $response->json())
    ->catch(fn ($error) => echo "Error: " . $error->getMessage())
    ->finally(fn () => echo "Request completed.");

// GET request with query parameters
$response = get('https://api.example.com/users', ['page' => 1, 'limit' => 10]);

// POST request with JSON data
$response = post('https://api.example.com/users', [
    'name' => 'John Doe',
    'email' => '[email protected]'
]);

// Chain methods to build your request
$response = fetch_client()
    ->baseUri('https://api.example.com')
    ->withHeaders(['Accept' => 'application/json'])
    ->withToken('your-auth-token')
    ->withQueryParameters(['page' => 1, 'limit' => 10])
    ->get('/users');

use function Matrix\Support\async;
use function Matrix\Support\await;

$response = await(async(fn() => fetch('https://api.example.com/users')));
$users = $response->json();
echo "Fetched " . count($users) . " users";

// These async functions are provided by the Matrix library dependency
use function Matrix\Support\async;
use function Matrix\Support\await;
use function Matrix\Support\all;

// Execute an async function
await(async(function() {
    // Create multiple requests
    $results = await(all([
        'users' => async(fn() => fetch('https://api.example.com/users')),
        'posts' => async(fn() => fetch('https://api.example.com/posts')),
        'comments' => async(fn() => fetch('https://api.example.com/comments'))
    ]));

    // Process the results
    $users = $results['users']->json();
    $posts = $results['posts']->json();
    $comments = $results['comments']->json();

    echo "Fetched " . count($users) . " users, " .
         count($posts) . " posts, and " .
         count($comments) . " comments";
}));

use function Matrix\Support\async;
use function Matrix\Support\await;

await(async(function() {
    // First request: get auth token
    $authResponse = await(async(fn() =>
        fetch('https://api.example.com/auth/login', [
            'method' => 'POST',
            'json' => [
                'username' => 'user',
                'password' => 'pass'
            ]
        ])
    ));

    $token = $authResponse->json()['token'];

    // Second request: use token to get user data
    $userResponse = await(async(fn() =>
        fetch('https://api.example.com/me', [
            'token' => $token
        ])
    ));

    return $userResponse->json();
}));

use function Matrix\Support\async;
use function Matrix\Support\await;

try {
    $data = await(async(function() {
        $response = await(async(fn() =>
            fetch('https://api.example.com/users/999')
        ));

        if ($response->isNotFound()) {
            throw new \Exception("User not found");
        }

        return $response->json();
    }));

    // Process the data

} catch (\Exception $e) {
    echo "Error: " . $e->getMessage();
}

// Set up an async request
// Get the handler for async operations
$handler = fetch_client()->getHandler();
$handler->async();

// Make the async request
$promise = $handler->get('https://api.example.com/users');

// Handle the result with callbacks
$promise->then(
    function ($response) {
        // Process successful response
        $users = $response->json();
        foreach ($users as $user) {
            echo $user['name'] . PHP_EOL;
        }
    },
    function ($exception) {
        // Handle errors
        echo "Error: " . $exception->getMessage();
    }
);

use function Matrix\Support\race;

// Create promises for redundant endpoints
$promises = [
    async(fn() => fetch('https://api1.example.com/data')),
    async(fn() => fetch('https://api2.example.com/data')),
    async(fn() => fetch('https://api3.example.com/data'))
];

// Get the result from whichever completes first
$response = await(race($promises));
$data = $response->json();
echo "Got data from the fastest source";

use function Matrix\Support\map;

// List of user IDs to fetch
$userIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Process at most 3 requests at a time
$responses = await(map($userIds, function($id) {
    return async(function() use ($id) {
        return fetch("https://api.example.com/users/{$id}");
    });
}, 3));

// Process the responses
foreach ($responses as $index => $response) {
    $user = $response->json();
    echo "Processed user {$user['name']}\n";
}

use function Matrix\Support\batch;

// Array of items to process
$items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Process in batches of 3 with max 2 concurrent batches
$results = await(batch(
    $items,
    function($batch) {
        // Process a batch
        return async(function() use ($batch) {
            $batchResults = [];
            foreach ($batch as $id) {
                $response = await(async(fn() =>
                    fetch("https://api.example.com/users/{$id}")
                ));
                $batchResults[] = $response->json();
            }
            return $batchResults;
        });
    },
    3, // batch size
    2  // concurrency
));

use function Matrix\Support\retry;

// Retry a flaky request up to 3 times with exponential backoff
$data = await(retry(
    function() {
        return async(function() {
            return fetch('https://api.example.com/unstable-endpoint');
        });
    },
    3, // max attempts
    function($attempt) {
        // Exponential backoff strategy
        return min(pow(2, $attempt) * 100, 1000);
    }
));

$response = fetch_client()
    ->retry(3, 200)                // 3 retries, 200ms base delay
    ->retryStatusCodes([429, 503]) // optional: customize which statuses retry
    ->retryExceptions([ConnectException::class]) // optional: customize exception types
    ->get('https://api.example.com/unstable');

// Basic auth
$response = fetch('https://api.example.com/secure', [
    'auth' => ['username', 'password']
]);

// Bearer token
$response = fetch_client()
    ->withToken('your-oauth-token')
    ->get('https://api.example.com/secure');

$response = fetch('https://api.example.com', [
    'proxy' => 'http://proxy.example.com:8080'
]);

// Or with fluent API
$response = fetch_client()
    ->withProxy('http://proxy.example.com:8080')
    ->get('https://api.example.com');

// Configure once at application bootstrap
fetch_client([
    'base_uri' => 'https://api.example.com',
    'headers' => [
        'User-Agent' => 'MyApp/1.0',
        'Accept' => 'application/json',
    ],
    'timeout' => 10,
]);

// Use the configured client throughout your application
function getUserData($userId) {
    return fetch_client()->get("/users/{$userId}")->json();
}

function createUser($userData) {
    return fetch_client()->post('/users', $userData)->json();
}

$response = fetch('https://api.example.com/users/1');

// Check if request was successful
if ($response->successful()) {
    // HTTP status code
    echo $response->getStatusCode(); // 200

    // Response body as JSON (returns array by default)
    $user = $response->json();

    // Response body as object
    $userObject = $response->object();

    // Response body as array
    $userArray = $response->array();

    // Response body as string
    $body = $response->text();

    // Get a specific header
    $contentType = $response->getHeaderLine('Content-Type');

    // Check status code categories
    if ($response->isSuccess()) {
        echo "Request succeeded (2xx)";
    }

    if ($response->isOk()) {
        echo "Request returned 200 OK";
    }

    if ($response->isNotFound()) {
        echo "Resource not found (404)";
    }
}

// ArrayAccess support
$name = $response['name']; // Access JSON response data directly

// Inspect retry-related statuses explicitly if needed
if ($response->getStatusCode() === 429) {
    // Handle rate limit response
}

## Working with Type-Safe Enums


// Synchronous error handling
try {
    $response = fetch('https://api.example.com/nonexistent');

    if (!$response->successful()) {
        echo "Request failed with status: " . $response->getStatusCode();
    }
} catch (\Throwable $e) {
    echo "Exception: " . $e->getMessage();
}

// Asynchronous error handling
$handler = fetch_client()->getHandler();
$handler->async();

$promise = $handler->get('https://api.example.com/nonexistent')
    ->then(function ($response) {
        if ($response->successful()) {
            return $response->json();
        }
        throw new \Exception("Request failed with status: " . $response->getStatusCode());
    })
    ->catch(function (\Throwable $e) {
        echo "Error: " . $e->getMessage();
    });

$response = fetch('https://api.example.com/data', [
    'timeout' => 15,          // total request timeout (seconds)
    'connect_timeout' => 5,   // connection timeout (seconds)
]);

use Fetch\Cache\MemoryCache;
use Fetch\Cache\FileCache;

$handler = fetch_client()->getHandler();

// Enable cache with in-memory backend (default)
$handler->withCache();

// Or use file-based cache
$handler->withCache(new FileCache('/path/to/cache'));

// Disable cache
$handler->withoutCache();

$response = $handler->get('https://api.example.com/users');

$handler->withCache(null, [
    'default_ttl' => 3600,                  // Default TTL in seconds (overridden by Cache-Control)
    'respect_cache_headers' => true,        // Honor Cache-Control headers (default: true)
    'is_shared_cache' => false,             // Act as shared cache (respects s-maxage)
    'stale_while_revalidate' => 60,         // Serve stale for 60s while revalidating
    'stale_if_error' => 300,                // Serve stale for 300s if backend fails
    'vary_headers' => ['Accept', 'Accept-Language'], // Headers to vary cache by
    'cache_methods' => ['GET', 'HEAD'],     // Cacheable HTTP methods
    'cache_status_codes' => [200, 301],     // Cacheable status codes
]);

// Force a fresh request (bypass cache)
$response = $handler->withOptions(['cache' => ['force_refresh' => true]])
    ->get('https://api.example.com/users');

// Custom TTL for specific request
$response = $handler->withOptions(['cache' => ['ttl' => 600]])
    ->get('https://api.example.com/users');

// Custom cache key
$response = $handler->withOptions(['cache' => ['key' => 'custom:users']])
    ->get('https://api.example.com/users');

// Cache POST/PUT payloads ( `withCache()` and set `cache_body => true` so the request body participates in the cache key.
- **Static assets**: pin a custom `key` for predictable lookups regardless of URL params.

$handler = fetch_client()->getHandler();

// Enable with default settings
$handler->withConnectionPool(true);

// Or configure with custom options
$handler->withConnectionPool([
    'enabled' => true,
    'max_connections' => 50,        // Total connections across all hosts
    'max_per_host' => 10,           // Max connections per host
    'max_idle_per_host' => 5,       // Idle sockets kept per host
    'keep_alive_timeout' => 60,     // Connection lifetime in seconds
    'connection_timeout' => 5,      // Dial timeout in seconds
    'dns_cache_ttl' => 300,         // DNS cache TTL in seconds
    'connection_warmup' => false,
    'warmup_connections' => 0,
]);

// Enable HTTP/2 (p2(true);

// Or configure with options
$handler->withHttp2([
    'enabled' => true,
    // Additional HTTP/2 configuration options...
]);

// Get pool statistics
$stats = $handler->getPoolStats();
// Returns: connections_created, connections_reused, total_requests, average_latency, reuse_rate

// Close all active connections
$handler->closeAllConnections();

// Reset pool and DNS cache (useful for testing)
$handler->resetPool();

$handler = fetch_client()->getHandler();

// Enable debug with default options (captures everything)
$handler->withDebug();

// Or enable with specific options
$handler->withDebug([
    'request_headers' => true,
    'request_body' => true,
    'response_headers' => true,
    'response_body' => 1024,  // Truncate response body at 1024 bytes
    'timing' => true,
    'memory' => true,
    'dns_resolution' => true,
]);

// Enable profiling
$handler->withProfiler(new \Fetch\Support\FetchProfiler);

// Set log level (

use Fetch\Testing\MockServer;
use Fetch\Testing\MockResponse;

// Mock a single response
MockServer::fake([
    'GET https://api.example.com/users/1' => MockResponse::json([
        'id' => 1,
        'name' => 'Ada Lovelace',
    ]),
]);

$response = fetch('https://api.example.com/users/1');
// Returns mocked response without making an actual HTTP request
MockServer::assertSent('GET https://api.example.com/users/1');

// Mock a sequence of responses
MockServer::fake([
    'https://api.example.com/users/*' => MockResponse::sequence([
        MockResponse::json(['id' => 1]),
        MockResponse::json(['id' => 2]),
        MockResponse::notFound(),
    ]),
]);

fetch('https://api.example.com/users/alpha'); // gets id 1
fetch('https://api.example.com/users/beta');  // gets id 2
fetch('https://api.example.com/users/omega'); // 404 from sequence

$response = fetch('https://api.example.com/data');

// Status category checks
$response->isInformational(); // 1xx
$response->isSuccess();       // 2xx
$response->isRedirection();   // 3xx
$response->isClientError();   // 4xx
$response->isServerError();   // 5xx

// Specific status checks
$response->isOk();            // 200
$response->isCreated();       // 201
$response->isNoContent();     // 204
$response->isNotFound();      // 404
$response->isForbidden();     // 403
$response->isUnauthorized();  // 401

// Generic status check
$response->isStatus(Status::CREATED);
$response->isStatus(201);

// Check if response contains JSON
if ($response->isJson()) {
    $data = $response->json();
}

// Get response as different types with error handling
$data = $response->json(assoc: true, throwOnError: false);
$object = $response->object(throwOnError: false);
$array = $response->array(throwOnError: false);

$handler = fetch_client()->getHandler();

// Close all active connections
$handler->closeAllConnections();

// Reset the entire pool and DNS cache (useful in tests)
$handler->resetPool();

// Get pool statistics
$stats = $handler->getPoolStats();
// Returns: connections_created, connections_reused, total_requests, average_latency, reuse_rate
bash
composer