title: Helper Functions description: Learn about the helper functions available in the Fetch HTTP package#
Helper Functions#
The Fetch HTTP package provides a set of global helper functions that offer a simpler, more direct way to make HTTP requests. These functions are designed to be familiar for developers who have experience with JavaScript's fetch API or other HTTP client libraries.
Main Functions#
fetch()#
The primary helper function that mimics JavaScript's fetch() API. It provides a simple yet powerful way to make HTTP requests.
function fetch(
string|RequestInterface|null $resource = null,
?array $options = []
): ResponseInterface|ClientHandlerInterface|Client
Parameters#
$resource: A URL string, aRequestobject, ornullto return the client for chaining$options: An array of request options, including:method: HTTP method (string orMethodenum)headers: Request headers (array)body: Request body (mixed)json: JSON data to send as body (array, takes precedence over body)form: Form data to send as body (array, takes precedence if no json)multipart: Multipart form data (array, takes precedence if no json/form)query: Query parameters (array)base_uri: Base URI (string)timeout: Request timeout in seconds (int)retries: Number of retries (int)auth: Basic auth credentials [username, password] (array)token: Bearer token (string)- Plus other options like
proxy,cookies,allow_redirects, etc.
Return Value#
- If
$resourceisnull: Returns the client instance for method chaining - If
$resourceis a URL string: Returns aResponseobject - If
$resourceis aRequestobject: Returns aResponseobject
Examples#
Basic GET request:
$response = fetch('https://api.example.com/users');
$users = $response->json();
POST request with JSON data:
$response = fetch('https://api.example.com/users', [
'method' => 'POST',
'json' => ['name' => 'John Doe', 'email' => 'john@example.com']
]);
Setting headers:
$response = fetch('https://api.example.com/users', [
'headers' => [
'Authorization' => 'Bearer token123',
'Accept' => 'application/json'
]
]);
Using query parameters:
$response = fetch('https://api.example.com/users', [
'query' => ['page' => 1, 'per_page' => 20]
]);
Method chaining:
fetch()
->withToken('your-token')
->withHeader('Accept', 'application/json')
->get('https://api.example.com/users');
fetch_client()#
Gets or configures the global fetch client instance.
function fetch_client(
?array $options = null,
bool $reset = false
): Client
Parameters#
$options: Global client options$reset: Whether to reset the client instance
Return Value#
Returns the global Client instance.
Examples#
Get the default client:
$client = fetch_client();
Configure the global client:
fetch_client([
'base_uri' => 'https://api.example.com',
'timeout' => 10,
'headers' => [
'User-Agent' => 'MyApp/1.0'
]
]);
// Now all fetch() calls will use these settings by default
$response = fetch('/users'); // Uses the base_uri
Reset the client:
fetch_client(reset: true);
Add a logger:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('http');
$logger->pushHandler(new StreamHandler('logs/http.log', Logger::DEBUG));
// Set the logger on the client
$client = fetch_client();
$client->setLogger($logger);
HTTP Method Helpers#
The package provides shorthand functions for common HTTP methods, making your code more concise and readable.
get()#
function get(
string $url,
?array $query = null,
?array $options = []
): ResponseInterface
Examples#
Simple GET request:
$response = get('https://api.example.com/users');
GET with query parameters:
$response = get('https://api.example.com/users', [
'page' => 1,
'per_page' => 20
]);
GET with additional options:
$response = get('https://api.example.com/users', null, [
'headers' => ['Accept' => 'application/json'],
'timeout' => 5
]);
post()#
function post(
string $url,
mixed $data = null,
?array $options = []
): ResponseInterface
Examples#
POST with JSON data (arrays are automatically converted to JSON):
$response = post('https://api.example.com/users', [
'name' => 'John Doe',
'email' => 'john@example.com'
]);
POST with raw data:
$response = post('https://api.example.com/webhook', 'Raw content', [
'headers' => ['Content-Type' => 'text/plain']
]);
POST with form data:
$response = post('https://api.example.com/login', null, [
'form' => [
'username' => 'johndoe',
'password' => 'secret'
]
]);
put()#
function put(
string $url,
mixed $data = null,
?array $options = []
): ResponseInterface
Examples#
$response = put('https://api.example.com/users/123', [
'name' => 'John Smith',
'email' => 'john.smith@example.com'
]);
patch()#
function patch(
string $url,
mixed $data = null,
?array $options = []
): ResponseInterface
Examples#
$response = patch('https://api.example.com/users/123', [
'status' => 'active'
]);
delete()#
function delete(
string $url,
mixed $data = null,
?array $options = []
): ResponseInterface
Examples#
Simple DELETE:
$response = delete('https://api.example.com/users/123');
DELETE with body:
$response = delete('https://api.example.com/users/batch', [
'ids' => [123, 456, 789]
]);
Async/Promise Functions#
The Fetch PHP package includes a set of functions for working with asynchronous requests and promises.
async()#
Wraps a function to run asynchronously and returns a promise.
function async(callable $fn): PromiseInterface
Example#
$promise = async(function() {
return fetch('https://api.example.com/users');
});
await()#
Waits for a promise to resolve and returns its value.
function await(PromiseInterface $promise): mixed
Example#
$response = await(async(function() {
return fetch('https://api.example.com/users');
}));
$users = $response->json();
all()#
Executes multiple promises concurrently and waits for all to complete.
function all(array $promises): PromiseInterface
Example#
$results = await(all([
'users' => async(fn() => fetch('https://api.example.com/users')),
'posts' => async(fn() => fetch('https://api.example.com/posts'))
]));
$users = $results['users']->json();
$posts = $results['posts']->json();
race()#
Executes multiple promises concurrently and returns the first to complete.
function race(array $promises): PromiseInterface
Example#
$response = await(race([
async(fn() => fetch('https://api1.example.com/data')),
async(fn() => fetch('https://api2.example.com/data'))
]));
any()#
Executes multiple promises concurrently and returns the first to succeed.
function any(array $promises): PromiseInterface
Example#
$response = await(any([
async(fn() => fetch('https://api1.example.com/data')),
async(fn() => fetch('https://api2.example.com/data'))
]));
map()#
Maps an array of items through an async function with controlled concurrency.
function map(array $items, callable $callback, int $concurrency = 5): PromiseInterface
Example#
$responses = await(map([1, 2, 3, 4, 5], function($id) {
return async(function() use ($id) {
return fetch("https://api.example.com/users/{$id}");
});
}, 3)); // Process at most 3 items concurrently
batch()#
Processes items in batches with controlled concurrency.
function batch(
array $items,
callable $callback,
int $batchSize = 10,
int $concurrency = 5
): PromiseInterface
Example#
$results = await(batch(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
function($batch) {
return async(function() use ($batch) {
$results = [];
foreach ($batch as $id) {
$response = await(async(fn() =>
fetch("https://api.example.com/users/{$id}")
));
$results[] = $response->json();
}
return $results;
});
},
3, // batch size
2 // concurrency
));
retry()#
Retries an async operation with exponential backoff.
function retry(
callable $fn,
int $attempts = 3,
callable|int $delay = 100
): PromiseInterface
Example#
$response = 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);
}
));
Using Helper Functions in Real-World Examples#
Basic API Interaction#
// Fetch a list of users
$users = get('https://api.example.com/users')->json();
// Create a new user
$user = post('https://api.example.com/users', [
'name' => 'John Doe',
'email' => 'john@example.com'
])->json();
// Update a user
$updatedUser = put("https://api.example.com/users/{$user['id']}", [
'name' => 'John Smith'
])->json();
// Delete a user
delete("https://api.example.com/users/{$user['id']}");
Authentication#
// Configure client with authentication
fetch_client([
'base_uri' => 'https://api.example.com',
'headers' => [
'Authorization' => 'Bearer your-oauth-token'
]
]);
// All requests now include authentication
$response = get('/protected-resource');
// Or using the withToken method
$response = fetch_client()
->withToken('your-oauth-token')
->get('/protected-resource');
// Basic authentication
$response = fetch_client()
->withAuth('username', 'password')
->get('/protected-resource');
File Upload#
$response = fetch('https://api.example.com/upload', [
'method' => 'POST',
'multipart' => [
[
'name' => 'file',
'contents' => file_get_contents('/path/to/image.jpg'),
'filename' => 'upload.jpg',
'headers' => ['Content-Type' => 'image/jpeg']
],
[
'name' => 'description',
'contents' => 'Profile picture'
]
]
]);
// Using the fluent interface
$response = fetch_client()
->withMultipart([
[
'name' => 'file',
'contents' => fopen('/path/to/image.jpg', 'r'),
'filename' => 'upload.jpg',
],
[
'name' => 'description',
'contents' => 'Profile picture'
]
])
->post('https://api.example.com/upload');
// Check if upload was successful
if ($response->successful()) {
$fileUrl = $response->json()['url'];
echo "File uploaded successfully: {$fileUrl}";
}
Error Handling#
try {
$response = get('https://api.example.com/users/999');
if ($response->isNotFound()) {
echo "User not found!";
} elseif ($response->isUnauthorized()) {
echo "Authentication required!";
} elseif ($response->failed()) {
echo "Request failed with status: " . $response->status();
} else {
$user = $response->json();
echo "Found user: " . $user['name'];
}
} catch (\Fetch\Exceptions\NetworkException $e) {
echo "Network error: " . $e->getMessage();
} catch (\Fetch\Exceptions\RequestException $e) {
echo "Request error: " . $e->getMessage();
} catch (\Exception $e) {
echo "Error: " . $e->getMessage();
}
Parallel Requests with Modern Async/Await#
use function async;
use function await;
use function all;
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";
}));
Working with Content Types#
use Fetch\Enum\ContentType;
// Using string content types
$response = fetch_client()
->withBody($data, 'application/json')
->post('https://api.example.com/users');
// Using enum content types
$response = fetch_client()
->withBody($data, ContentType::JSON)
->post('https://api.example.com/users');
// Checking content type
if ($response->hasJsonContent()) {
$data = $response->json();
} elseif ($response->hasHtmlContent()) {
$html = $response->text();
}
Working with Enums#
use Fetch\Enum\Method;
use Fetch\Enum\ContentType;
use Fetch\Enum\Status;
// Use method enum
$response = fetch_client()->request(Method::POST, '/users', $userData);
// Check status with enum
if ($response->statusEnum() === Status::OK) {
// Process successful response
}
// Content type handling
$response = fetch_client()
->withBody($data, ContentType::JSON)
->post('/users');
Tips and Best Practices#
-
Configure Once, Use Everywhere: Use
fetch_client()to set global options and defaults that will apply to all requests.// Set up once at the beginning of your application fetch_client([ 'base_uri' => 'https://api.example.com', 'timeout' => 10, 'headers' => [ 'User-Agent' => 'MyApp/1.0', 'Accept' => 'application/json' ] ]); // Now use simplified calls throughout your code $users = get('/users')->json(); $user = get("/users/{$id}")->json(); -
Use Type-Safe Enums: Take advantage of PHP 8.1 enums for better type safety and code readability.
use Fetch\Enum\Method; use Fetch\Enum\ContentType; use Fetch\Enum\Status; $response = fetch_client()->request(Method::POST, '/users', $userData); if ($response->statusEnum() === Status::CREATED) { // User was created successfully } -
Use the Right Helper for the Job: Choose the appropriate helper function based on the HTTP method you need.
-
Handling JSON: Arrays passed to
post(),put(),patch(), anddelete()are automatically treated as JSON data. -
Leverage Method Chaining: When you need more control, use the fluent interface:
fetch() ->baseUri('https://api.example.com') ->withToken('your-token') ->timeout(5) ->retry(3, 100) ->get('/users'); -
Use the Response Methods: Take advantage of the response helper methods for cleaner code:
// Instead of: if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) { // ... } // Use: if ($response->successful()) { // ... } -
Modern Async/Await: Use
async()andawait()for cleaner asynchronous code:await(async(function() { $response = await(async(fn() => fetch('https://api.example.com/users'))); return $response->json(); })); -
Resource Conservation: When working with many requests, use controlled concurrency with
map()orbatch():$results = await(map($items, function($item) { return async(fn() => fetch("https://api.example.com/{$item}")); }, 5)); // No more than 5 concurrent requests
Next Steps#
- Learn more about Working with Responses
- Explore Asynchronous Requests for parallel HTTP operations
- Discover Retry Handling for dealing with unreliable APIs
- Learn about Working with Enums for type-safe HTTP operations