Выполнение запросов в PHP: сетевые вызовы и SQL
В современных PHP приложениях часто возникает необходимость отправлять HTTP запросы к внешним API или выполнять SQL запросы к базе данных. Для каждой задачи существует несколько подходов. Рассмотрим основные варианты.
Основные способы выполнения запросов в PHP: HTTP и SQL
Наиболее эффективное решение представляет собой комбинацию библиотеки cURL для HTTP запросов и расширения PDO для SQL запросов. Такой подход обеспечивает гибкость, безопасность и производительность.
Пример HTTP GET запроса через cURL:
$url = 'https://api.example.com/users';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // для тестовых окружений
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
}
Php get (обработка get запросов в php)
Пояснение: после инициализации дескриптора cURL задаётся URL, флаг CURLOPT_RETURNTRANSFER указывает вернуть результат в виде строки, CURLOPT_SSL_VERIFYPEER отключает проверку SSL сертификата (только для отладки). Выполнение запроса происходит через curl_exec, код ответа получается функцией curl_getinfo.
Пример безопасного SQL запроса через PDO:
$dsn = 'mysql:host=localhost;dbname=test;charset=utf8';
$user = 'root';
$pass = '';
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
$id = 1;
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
$user = $stmt->fetch();
Php file http (работа с файлами по http в php)
Пояснение: создаётся объект PDO с параметрами подключения. Устанавливается режим ошибок исключений и режим выборки ассоциативных массивов. Подготовленный запрос с плейсхолдером ? защищает от SQL инъекций.
Типичная проблема: расширение cURL может отсутствовать на сервере. Решение - проверить extension_loaded('curl') и вывести альтернативное сообщение. Для PDO часто возникает ошибка подключения из-за неверного DSN или отсутствия драйвера. Рекомендуется обернуть создание PDO в блок try-catch.
Как выполнить HTTP запрос без установки дополнительных расширений?
Метод file_get_contents с контекстом потока подходит для простых GET и POST запросов.
$data = ['name' => 'test', 'email' => 'test@example.com'];
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query($data)
]
];
$context = stream_context_create($options);
$result = @file_get_contents('https://api.example.com/endpoint', false, $context);
if ($result === false) {
$error = error_get_last();
// обработка ошибки
}
Http content php (отправка контента по http в php)
Пояснение: функция http_build_query преобразует массив в URL-кодированную строку. Контекст создаётся через stream_context_create. Символ @ подавляет вывод предупреждений, затем нужно проверить результат.
Типичные ошибки: функция возвращает false при недоступности сервера или ошибках соединения, при этом сообщение об ошибке скрыто. Решение - использовать error_get_last() после проверки. Также возможна проблема с таймаутами, для чего в контекст добавляется опция 'timeout' => 5.
Как упростить сложные HTTP запросы с помощью библиотеки Guzzle?
Guzzle предоставляет высокоуровневый API для отправки запросов, поддерживает middleware, асинхронность и PSR-7.
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client(['base_uri' => 'https://api.example.com']);
$response = $client->post('/endpoint', [
'json' => ['key' => 'value'],
'headers' => ['Authorization' => 'Bearer token']
]);
$body = $response->getBody()->getContents();
Php https post (отправка https post запросов в php)
Пояснение: после подключения через Composer создаётся клиент с базовым URI. Метод post принимает массив опций, где 'json' автоматически кодирует тело запроса. Ответ - объект PSR-7 Response.
Типичные проблемы: необходимость установки Composer и самой библиотеки может быть избыточной для простых проектов. Версии Guzzle 6 и 7 имеют различия; рекомендуется использовать последнюю стабильную версию. Также возможны проблемы с правами на запись в кеш пакетов.
Как работать с MySQL напрямую, если PDO недоступен?
Расширение mysqli предоставляет объектно-ориентированный интерфейс для MySQL.
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
if ($mysqli->connect_error) {
die('Ошибка подключения: ' . $mysqli->connect_error);
}
$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
Php post json (php: отправка post-запроса с json)
Пояснение: создаётся объект mysqli, проверяется ошибка соединения. Подготовленный запрос с плейсхолдером ? требует вызова bind_param с указанием типов параметров.
Типичные ошибки: забытый вызов bind_param или неверный тип 'i' (integer) приводит к ошибкам выполнения. Также вероятна SQL инъекция, если данные вставляются напрямую в строку запроса. Решение - всегда использовать подготовленные выражения.
Какие риски возникают при конкатенации строк SQL?
Прямое встраивание переменных в запрос создаёт уязвимость для SQL инъекций. Это антипаттерн, но его демонстрация помогает понять важность подготовленных запросов.
$id = $_GET['id'];
$pdo->query("SELECT * FROM users WHERE id = $id"); // уязвимо!
Пояснение: если $id содержит 1 OR 1=1, запрос вернёт все записи.
Ошибка: отсутствие экранирования приводит к потере данных или их утечке. Единственное надёжное решение - использование подготовленных запросов с плейсхолдерами, предоставляемыми PDO или mysqli.
Расширенные примеры выполнения запросов в PHP
Пример 1. POST запрос с JSON через cURL и проверка кода ответа
$url = 'https://api.example.com/users/create';
$data = ['name' => 'Алексей', 'email' => 'alexey@example.com'];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 201) {
$result = json_decode($response, true);
echo "Создан пользователь с ID: " . $result['id'];
} else {
echo "Ошибка. Код: $httpCode, тело: $response";
}
Создан пользователь с ID: 42
Пояснение: устанавливается метод POST, тело запроса кодируется в JSON. Заголовки задают тип данных. Код ответа 201 указывает на успешное создание ресурса. При ошибке выводится код и тело ответа для диагностики.
Пример 2. Асинхронный GET запрос с помощью Guzzle (Promises)
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(['base_uri' => 'https://api.example.com']);
$promises = [
'users' => $client->getAsync('/users'),
'posts' => $client->getAsync('/posts')
];
$results = Promise\Utils::settle($promises)->wait();
foreach ($results as $key => $result) {
if ($result['state'] === 'fulfilled') {
$body = $result['value']->getBody()->getContents();
echo "$key: успешно, длина " . strlen($body) . " байт\n";
} else {
echo "$key: ошибка " . $result['reason'] . "\n";
}
}
users: успешно, длина 1254 байт posts: успешно, длина 9843 байт
Пояснение: методы getAsync возвращают обещания. Функция settle ожидает выполнения всех обещаний, не прерываясь при первой ошибке. Результат содержит состояние 'fulfilled' или 'rejected'. Асинхронность позволяет параллельно выполнять несколько запросов.
Пример 3. Транзакция в PDO при массовой вставке с откатом
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare('INSERT INTO orders (product_id, quantity) VALUES (?, ?)');
$items = [
[1, 2],
[3, 5],
[7, 1]
];
foreach ($items as $item) {
$stmt->execute($item);
}
$pdo->commit();
echo "Заказы успешно добавлены";
} catch (PDOException $e) {
$pdo->rollBack();
echo "Ошибка при вставке: " . $e->getMessage();
}
Заказы успешно добавлены
Пояснение: транзакция начинается с beginTransaction. В случае исключения любой операции выполняется rollBack, отменяющий все изменения. После успешного завершения всех запросов вызывается commit.
Пример 4. Загрузка файла через cURL (multipart/form-data)
$url = 'https://api.example.com/upload';
$filePath = '/path/to/image.jpg';
$curlFile = new CURLFile($filePath, 'image/jpeg', 'photo.jpg');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => $curlFile,
'description' => 'Отпуск 2024'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
echo "Файл загружен: " . $response;
} else {
echo "Ошибка загрузки: $httpCode";
}
Файл загружен: {"status":"success","file_id":123}
Пояснение: класс CURLFile создаёт объект файла с MIME-типом и именем. Массив CURLOPT_POSTFIELDS автоматически формирует multipart/form-data запрос. Важно указывать абсолютный путь к файлу.