PHP
Building a Generic API Wrapper Class (PHP)
Develop a reusable PHP class to efficiently interact with various RESTful APIs, centralizing HTTP requests, header management, and error handling.
<?php
class ApiClient {
private $baseUrl;
private $headers = [];
private $lastError = null;
public function __construct($baseUrl, $defaultHeaders = []) {
$this->baseUrl = rtrim($baseUrl, '/');
$this->headers = array_merge([
'Content-Type: application/json',
'Accept: application/json'
], $defaultHeaders);
}
public function setHeader($name, $value) {
// Remove existing header with the same name before adding
$this->headers = array_filter($this->headers, function($header) use ($name) {
return strpos($header, $name . ':') !== 0;
});
$this->headers[] = "$name: $value";
return $this;
}
public function setAuthToken($token) {
return $this->setHeader('Authorization', 'Bearer ' . $token);
}
private function makeRequest($method, $path, $data = null) {
$url = $this->baseUrl . '/' . ltrim($path, '/');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30 second timeout
switch (strtoupper($method)) {
case 'POST':
curl_setopt($ch, CURLOPT_POST, true);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
break;
case 'PUT':
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
break;
case 'DELETE':
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
break;
// GET is default
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($response === false) {
$this->lastError = "cURL Error: " . $error;
return false;
}
$decodedResponse = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
$this->lastError = "JSON Decode Error: " . json_last_error_msg() . " - Raw: " . $response;
return false;
}
if ($httpCode >= 400) {
$this->lastError = "API Error (HTTP $httpCode): " . ($decodedResponse['message'] ?? 'Unknown error');
return false;
}
$this->lastError = null; // Clear error on success
return $decodedResponse;
}
public function get($path) {
return $this->makeRequest('GET', $path);
}
public function post($path, $data) {
return $this->makeRequest('POST', $path, $data);
}
public function put($path, $data) {
return $this->makeRequest('PUT', $path, $data);
}
public function delete($path) {
return $this->makeRequest('DELETE', $path);
}
public function getLastError() {
return $this->lastError;
}
}
// Example Usage:
/*
// require_once 'ApiClient.php'; // If in a separate file
$apiClient = new ApiClient('https://jsonplaceholder.typicode.com');
// Set a custom header or auth token
$apiClient->setAuthToken('YOUR_SUPER_SECRET_TOKEN');
// GET request
$posts = $apiClient->get('/posts');
if ($posts) {
// print_r($posts);
// echo "Fetched " . count($posts) . " posts.
";
} else {
// echo "Error fetching posts: " . $apiClient->getLastError() . "
";
}
// POST request
$newPost = [
'title' => 'foo',
'body' => 'bar',
'userId' => 1,
];
$createdPost = $apiClient->post('/posts', $newPost);
if ($createdPost) {
// echo "Created post with ID: " . $createdPost['id'] . "
";
// print_r($createdPost);
} else {
// echo "Error creating post: " . $apiClient->getLastError() . "
";
}
*/
How it works: This PHP `ApiClient` class provides a generic wrapper for interacting with RESTful APIs. It centralizes common API tasks like setting base URLs, managing headers (including authorization tokens), and making `GET`, `POST`, `PUT`, and `DELETE` requests. The class handles `cURL` execution, JSON decoding, and basic error detection for network issues, API errors (HTTP 4xx/5xx), and JSON parsing, making API integrations cleaner and more maintainable.