Выполнение запросов в PHP: сетевые вызовы и SQL

Раздел: Разработка на PHP -> HTTP запросы

В современных 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 get request (get запрос в php)
- Php post request (post запрос в php)
- Home php id index (передача параметра id в home.php)

Расширенные примеры выполнения запросов в 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 запрос. Важно указывать абсолютный путь к файлу.

PHP запросы (SQL/HTTP) - comments

En
Php запросы (php)