PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 13 · От основ к практике
Предопределённые переменные: CLI, HTTP, сессии и загрузки
От источника данных до безопасной проверки суперглобальных и специальных переменных.
$argv: значения после имени команды
Реальная потребность: запустить импорт, резервное копирование или фоновую задачу с параметрами без редактирования файла. Оболочка разбирает командную строку по своим правилам и передаёт PHP готовый список строк; $argv — этот индексированный массив.
<?php
echo 'Сценарий: ', basename($argv[0]), "\n";
echo 'Пользовательских аргументов: ', $argc - 1, "\n";
Ожидаемый результат
Сценарий: example.php
Пользовательских аргументов: 0
PHP CLI помещает имя запущенного файла в $argv[0], поэтому $argc равен как минимум 1. Пользовательские значения начинаются с индекса 1. В веб-запросе эти переменные могут отсутствовать: это интерфейс командной строки.
<?php
function readCommand(array $arguments): array
{
$input = $arguments[1] ?? null;
$dryRun = in_array('--dry-run', $arguments, true);
if ($input === null) {
return ['ok' => false, 'message' => 'Укажите CSV-файл'];
}
return ['ok' => true, 'input' => $input, 'dryRun' => $dryRun];
}
$command = readCommand(['import.php', 'orders.csv', '--dry-run']);
echo $command['input'], "\n";
echo $command['dryRun'] ? "Без записи\n" : "С записью\n";
Ожидаемый результат
orders.csv
Без записи
Для воспроизводимой проверки массив аргументов задан явно. В настоящем CLI-входе передайте в функцию глобальный $argv. Оператор ?? задаёт запасное значение, а строгое сравнение в in_array не смешивает строки с числами.
Для сложных опций пригодится getopt(). Пути всё равно проверяют до открытия файла; сам факт присутствия строки ничего не говорит о доступности.
$argc: сколько элементов PHP передал сценарию
$argc содержит число элементов $argv, включая имя сценария. Поэтому проверка «передан ли один пользовательский аргумент» выглядит как $argc >= 2. count($argv) даёт то же количество, но $argc сразу сообщает назначение.
- Оболочка запускает PHP и передаёт два токена после настроек PHP.
- В
$argv[0]оказывается путь import.php, в$argv[1]— orders.csv. $argcравен 2; пользовательских значений —$argc - 1.- Код проверяет количество и только затем читает нужный индекс.
$http_response_header: метаданные ответа HTTP-wrapper
Когда file_get_contents() открывает HTTP/HTTPS URL, PHP создаёт в текущей локальной области массив строк ответа: первая строка содержит статус, остальные — заголовки. Это не заголовки входящего запроса к вашему сайту и не массив $_SERVER.
<?php
function indexHeaders(array $lines): array
{
$result = ['status' => array_shift($lines), 'headers' => []];
foreach ($lines as $line) {
[$name, $value] = array_map('trim', explode(':', $line, 2));
$result['headers'][strtolower($name)][] = $value;
}
return $result;
}
$response = indexHeaders([
'HTTP/1.1 200 OK',
'Content-Type: application/json',
'Set-Cookie: region=ru',
'Set-Cookie: theme=light',
]);
echo $response['status'], "\n";
echo $response['headers']['content-type'][0], "\n";
echo count($response['headers']['set-cookie']), " cookies\n";
Ожидаемый результат
HTTP/1.1 200 OK
application/json
2 cookies
Фикстура повторяет форму данных HTTP-wrapper без сетевого запроса. Один заголовок может встретиться несколько раз, поэтому значения сохраняются списком; разбиение ограничено двумя частями, чтобы двоеточие внутри значения не потерялось.
<?php
$context = stream_context_create([
'http' => ['timeout' => 3.0, 'ignore_errors' => true],
]);
$body = file_get_contents('https://example.com/', false, $context);
if ($body === false) {
throw new RuntimeException('HTTP-запрос не выполнен');
}
$headers = http_get_last_response_headers();
var_dump($headers[0] ?? null);
Контекстный пример требует сети, включённого HTTP-wrapper и PHP с http_get_last_response_headers(). Вывод зависит от ответа сервера, поэтому пример только проверяется синтаксически. В PHP 8.5 переменная $http_response_header устарела; современная функция явно выражает намерение.
$php_errormsg: почему старую глобальную переменную больше не используют
Эта переменная нужна прежде всего для понимания старого проекта. Она содержала текст последней ошибки в области, где произошла ошибка, но зависела от настройки и легко перезаписывалась следующим предупреждением.
<?php
error_clear_last();
@file_get_contents(__DIR__ . '/missing.txt');
$error = error_get_last();
echo $error === null ? "Ошибки нет\n" : "Предупреждение сохранено\n";
Ожидаемый результат
Предупреждение сохранено
@ здесь использован только для учебной демонстрации: он скрывает показ, но error_get_last() всё равно позволяет прочитать сведения. В приложении заранее проверяют путь или обрабатывают конкретную ошибку, а не прячут все предупреждения.
<?php
// Только для чтения старого кода PHP 7.1 и более раннего:
ini_set('track_errors', '1');
@file_get_contents(__DIR__ . '/missing.txt');
echo $php_errormsg;
$php_errormsg зависела от устаревшей настройки track_errors, была deprecated в PHP 7.2 и удалена в PHP 8.0. Фрагмент намеренно не исполняется и не должен копироваться в современный проект.
Для нормального потока используйте возвращаемые значения, исключения и явную обработку ошибок. error_get_last() — диагностический снимок, а не замена такой обработке.
$_SESSION: состояние между HTTP-запросами
HTTP-запросы независимы. Сессия связывает случайный идентификатор клиента с данными на сервере: корзиной, одноразовым сообщением или этапом формы. После session_start() PHP читает хранилище и заполняет суперглобальный массив.
- Браузер отправляет идентификатор сессии в cookie.
session_start()открывает серверное хранилище и заполняет$_SESSION.- Код читает или меняет ключи массива.
- PHP сохраняет изменения; следующий запрос с тем же идентификатором увидит их.
<?php
$store = __DIR__ . '/session-data';
if (!is_dir($store)) {
mkdir($store);
}
ini_set('session.use_cookies', '0');
session_save_path($store);
session_id('lesson-session');
session_start();
$_SESSION['customerName'] = 'Анна';
session_write_close();
session_id('lesson-session');
session_start();
echo 'Покупатель: ', $_SESSION['customerName'], "\n";
$_SESSION = [];
session_destroy();
Ожидаемый результат
Покупатель: Анна
Пример создаёт собственный каталог внутри распакованного архива и не трогает системную сессию. session_start() загружает данные в $_SESSION; session_write_close() сохраняет их и освобождает блокировку.
$_FILES: что именно приходит из HTML-формы
Поле <input type="file" name="avatar"> при форме с method="post" и enctype="multipart/form-data" создаёт $_FILES['avatar']. Текстовые поля той же формы оказываются в $_POST.
| Ключ | Что означает | Можно ли доверять |
|---|---|---|
| name / full_path | Имя и относительный путь от клиента | Нет; не используйте как серверный путь |
| type | MIME, заявленный клиентом | Нет; определите через finfo |
| tmp_name | Временный файл PHP | Проверить is_uploaded_file |
| error | Код UPLOAD_ERR_* | Проверить первым |
| size | Размер принятого временного файла | Проверить вместе с серверными лимитами |
<?php
$upload = [
'name' => 'avatar.png',
'full_path' => 'avatar.png',
'type' => 'image/png',
'tmp_name' => '/tmp/phpABC',
'error' => UPLOAD_ERR_OK,
'size' => 2048,
];
echo $upload['name'], "\n";
echo $upload['size'], " bytes\n";
echo $upload['error'] === UPLOAD_ERR_OK ? "Передан PHP\n" : "Ошибка загрузки\n";
Ожидаемый результат
avatar.png
2048 bytes
Передан PHP
Массив задан как безопасная фикстура, чтобы увидеть форму одной записи. name и type пришли от клиента и не доказывают содержимое; tmp_name в реальном запросе указывает на временный серверный файл.
<?php
if (!isset($_FILES['avatar']) || !is_array($_FILES['avatar'])) {
throw new RuntimeException('Поле avatar не отправлено');
}
$file = $_FILES['avatar'];
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException('Код ошибки загрузки: ' . $file['error']);
}
if ($file['size'] > 2_000_000 || !is_uploaded_file($file['tmp_name'])) {
throw new RuntimeException('Файл слишком большой или не является HTTP-загрузкой');
}
$mime = (new finfo(FILEINFO_MIME_TYPE))->file($file['tmp_name']);
$extension = ['image/jpeg' => 'jpg', 'image/png' => 'png'][$mime] ?? null;
if ($extension === null) {
throw new RuntimeException('Разрешены только JPEG и PNG');
}
$target = __DIR__ . '/uploads/' . bin2hex(random_bytes(16)) . '.' . $extension;
if (!move_uploaded_file($file['tmp_name'], $target)) {
throw new RuntimeException('Не удалось сохранить файл');
}
Это контекстный HTTP-обработчик: CLI не создаёт настоящую загрузку, поэтому заявлена только проверка синтаксиса. Каталог uploads заранее создают вне публично исполняемого места и задают ему минимальные права. Лимиты upload_max_filesize и post_max_size могут остановить запрос до прикладной проверки.
Связь HTML-поля, $_POST, CSRF и ответа подробно разобрана в главе о формах.
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


