.phpstan/MIGRATION_GUIDE_CURL.md
This guide helps you migrate from raw curl_* functions to GuzzleHttp, the modern HTTP client library used by OpenEMR.
Before (curl):
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
error_log("HTTP Error: $httpCode");
return null;
}
$data = json_decode($response, true);
After (Guzzle):
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
$client = new Client();
try {
$response = $client->request('GET', 'https://api.example.com/data');
$data = json_decode($response->getBody()->getContents(), true);
} catch (GuzzleException $e) {
error_log("HTTP Error: " . $e->getMessage());
return null;
}
Before (curl):
$data = ['key' => 'value'];
$jsonData = json_encode($data);
$ch = curl_init('https://api.example.com/endpoint');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($jsonData)
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
After (Guzzle):
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
$data = ['key' => 'value'];
$client = new Client();
try {
$response = $client->request('POST', 'https://api.example.com/endpoint', [
'json' => $data // Automatically sets Content-Type and encodes JSON
]);
$result = json_decode($response->getBody()->getContents(), true);
} catch (GuzzleException $e) {
error_log("HTTP Error: " . $e->getMessage());
return null;
}
Before (curl):
$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $token,
'Accept: application/json',
'User-Agent: OpenEMR/7.0'
]);
$response = curl_exec($ch);
curl_close($ch);
After (Guzzle):
use GuzzleHttp\Client;
$client = new Client();
$response = $client->request('GET', 'https://api.example.com/data', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
'User-Agent' => 'OpenEMR/7.0'
]
]);
Before (curl):
$filePath = '/path/to/file.pdf';
$ch = curl_init('https://api.example.com/upload');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile($filePath, 'application/pdf', 'document.pdf')
]);
$response = curl_exec($ch);
curl_close($ch);
After (Guzzle):
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Utils;
$client = new Client();
$response = $client->request('POST', 'https://api.example.com/upload', [
'multipart' => [
[
'name' => 'file',
'contents' => Utils::tryFopen('/path/to/file.pdf', 'r'),
'filename' => 'document.pdf'
]
]
]);
OpenEMR provides a convenient wrapper around Guzzle:
use OpenEMR\Common\Http\oeHttp;
try {
$response = oeHttp::get('https://api.example.com/data', [
'headers' => [
'Authorization' => 'Bearer ' . $token
]
]);
$data = json_decode($response->getBody()->getContents(), true);
} catch (\Exception $e) {
error_log("HTTP request failed: " . $e->getMessage());
}
Guzzle throws different exceptions for different error scenarios:
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException; // 4xx errors
use GuzzleHttp\Exception\ServerException; // 5xx errors
use GuzzleHttp\Exception\ConnectException; // Connection failures
use GuzzleHttp\Exception\RequestException; // General request errors
$client = new Client();
try {
$response = $client->request('GET', 'https://api.example.com/data');
} catch (ClientException $e) {
// 400-level errors (client errors)
$statusCode = $e->getResponse()->getStatusCode();
error_log("Client error: $statusCode - " . $e->getMessage());
} catch (ServerException $e) {
// 500-level errors (server errors)
$statusCode = $e->getResponse()->getStatusCode();
error_log("Server error: $statusCode - " . $e->getMessage());
} catch (ConnectException $e) {
// Connection failures (timeout, DNS, etc.)
error_log("Connection failed: " . $e->getMessage());
} catch (RequestException $e) {
// Other request-related errors
error_log("Request failed: " . $e->getMessage());
}
Before (curl):
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
After (Guzzle):
$client = new Client();
$response = $client->request('GET', 'https://api.example.com/data', [
'timeout' => 30, // Total timeout
'connect_timeout' => 10 // Connection timeout
]);
Before (curl):
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');
After (Guzzle):
$client = new Client();
$response = $client->request('GET', 'https://api.example.com/data', [
'verify' => '/path/to/cacert.pem', // Path to CA bundle, or false to disable
// Or use boolean: 'verify' => true/false
]);
src/Common/Http/oeHttp.phpsrc/Common/Http/oeOAuth.phpIf you need help migrating a complex curl usage pattern, please:
src/Common/Http/oeHttp.php for the convenience wrapper