Перейти к содержимому
Поиск
Php Разработка

PHP: полный мануал с примерами, функциями и ООП

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

Александр НекрасовИзменено:
Практический мануал PHP: от переменных и функций к объектной модели интернет-магазина
PHP 8.5.11468 глав6256 карточек справочника
Дерево руководства

Глава 219 · С нуля → рабочая команда

PHP в командной строке: аргументы, потоки, ini и локальный сервер

Полная официальная ветка CLI: чем SAPI отличается от веба, все группы опций, запуск файлов, argv, стандартные потоки, interactive shell, php -S и CLI ini.

CLI превращает PHP-файл в команду, импортёр или worker

CLI запускает PHP без HTTP-запроса: из терминала, планировщика, CI или supervisor. Так делают импорт каталога, миграцию, очередь и диагностическую команду. Входом становятся аргументы и STDIN, результатом — STDOUT/STDERR и exit code. Браузер, cookie, $_GET и HTTP-заголовки сами не появляются.

Команда импорта
  1. Вход: php import.php --limit=2 products.csv
  2. Действие: CLI передаёт argv, скрипт читает файл и печатает прогресс
  3. Результат: STDOUT для результата, STDERR для диагностики, exit 0/не 0 для планировщика
ЗапускКогда нужен
php script.phpОбычный файл; -f можно не писать.
php -r "code"Короткая одноразовая проверка без PHP-тегов; shell quoting зависит от оболочки.
php -aИнтерактивная оболочка, если сборка поддерживает readline.
php -S 127.0.0.1:8000 -t publicЛокальный HTTP-стенд, не production.
scheduler/supervisor → php worker.phpПовторяемый процесс с явными timeout, restart и журналом.

CLI и FPM — два способа запуска с разными входами и ini

SAPI — способ, которым окружение вызывает PHP. CLI не пишет HTTP-заголовки, показывает ошибки обычным текстом, не меняет текущий каталог на каталог файла и обычно имеет html_errors=0, implicit_flush=1, неограниченный max_execution_time, доступные $argc/$argv и отключённый обычный input-time. Проверяйте PHP_SAPI или php_sapi_name(), а не одно наличие $argv: register_argc_argv мог включить его в другом SAPI и с PHP 8.5 эта директива deprecated.

Увидеть SAPI, в котором действительно выполнен файлСамостоятельный пример
<?php
declare(strict_types=1);

echo 'SAPI: ', PHP_SAPI, "\n";
echo 'CLI: ', PHP_SAPI === 'cli' ? 'yes' : 'no', "\n";
echo 'HTTP headers: ', PHP_SAPI === 'cli' ? 'not emitted' : 'managed by SAPI', "\n";
echo 'argv available: ', isset($argv) ? 'yes' : 'no', "\n";
Ожидаемый результат
SAPI: cli
CLI: yes
HTTP headers: not emitted
argv available: yes

Проверка выполнится в CLI runtime. Веб-запуск покажет другой SAPI и не обязан иметь $argv.

РазличиеСледствие
Нет HTTP headersheader() не создаёт браузерный ответ; статус процесса задаёт exit.
Текущий каталог сохраняетсяОтносительный путь считается от cwd запуска. Для файлов рядом со скриптом используйте __DIR__.
Ошибки plain textЛоги удобны терминалу; HTML-разметка не вставляется.
max_execution_time обычно 0Долгий процесс всё равно получает собственный deadline, memory budget и supervisor.
CLI ini отдельныйУспех php -m не доказывает наличие расширения в FPM и наоборот.

Опции PHP binary: диагностика, конфигурация и запуск

Список вашей сборки всегда доступен через php -h. Перед аргументом, начинающимся с дефиса, ставьте --, чтобы PHP перестал разбирать собственные опции. Команда -l проверяет синтаксис, но не выполняет код и не обнаружит вызов отсутствующей функции.

ОпцияПрактическое действие
-aИнтерактивный режим.
-c path/fileДругой php.ini или каталог поиска.
-nНе читать php.ini.
-d name=valueПереопределить ini только для процесса.
-f file / fileВыполнить файл.
-h, -?Показать помощь.
-iphpinfo в формате текущего SAPI.
-lТолько parse/lint; до PHP 8.3 — один файл за запуск.
-mСписок PHP и Zend modules.
-r codeВыполнить короткий код без <?php.
-B / -R / -F / -EДо строк / код на строку / файл на строку / после строк STDIN.
-HСкрыть переданные аргументы от внешних инструментов, где поддерживается.
-S addr:port / -t docrootDevelopment server и его document root.
-s / -wПодсвеченный исходник / исходник без комментариев и пробелов.
-vВерсия binary и Zend Engine.
--ini[=diff]Загруженный ini и scan dirs; =diff появился в PHP 8.5.
--rf/--rc/--re/--rz/--riReflection по function/class/extension/Zend extension/ini extension.
Проверить binary, ini, modules и syntax перед запускомФрагмент или команда
# PowerShell
php -v
php --ini
php -m
php -l .\import.php
php --rf json_decode
php -d memory_limit=128M .\import.php -- --limit=50

# sh/bash: одинарные кавычки защищают $name от подстановки shell
php -r '$name="Анна"; echo $name, PHP_EOL;'

Команды относятся к оболочке, а не к синтаксису PHP, поэтому сохранены как contextual fragment. Версия и пути зависят от машины.

Файл, argv, getopt и разделитель --

В $argv[0] обычно находится имя скрипта, дальше — аргументы; $argc равно их количеству. Для простых именованных опций есть getopt(), для развитого интерфейса — библиотека console. Разбор ниже принимает фиксированный массив, чтобы точно показать договор; production передаст настоящий $argv.

Разобрать файл и именованный лимит до импортаСамостоятельный пример
<?php
declare(strict_types=1);

function parseImportArguments(array $argv): array
{
    $script = array_shift($argv);
    $limit = 100;
    $file = null;
    foreach ($argv as $argument) {
        if (str_starts_with($argument, '--limit=')) {
            $raw = substr($argument, 8);
            if ($raw === '' || !ctype_digit($raw) || (int) $raw < 1) {
                throw new InvalidArgumentException('limit должен быть целым > 0');
            }
            $limit = (int) $raw;
            continue;
        }
        if ($file !== null) { throw new InvalidArgumentException('Лишний аргумент'); }
        $file = $argument;
    }
    if ($file === null) { throw new InvalidArgumentException('Нужен CSV-файл'); }
    return ['script' => $script, 'limit' => $limit, 'file' => $file];
}

$options = parseImportArguments(['import.php', '--limit=2', 'products.csv']);
echo 'Файл: ', $options['file'], "\n";
echo 'Лимит: ', $options['limit'], "\n";
Ожидаемый результат
Файл: products.csv
Лимит: 2

Каждый новый элемент синтаксиса имеет роль: array_shift забирает argv[0], foreach читает аргументы, continue переходит к следующему, throw прекращает запуск с понятной ошибкой.

Unix shebang #!/usr/bin/env php позволяет сделать файл исполняемым; строка должна быть первой, а путь env зависит от системы. Windows обычно запускает явный php.exe script.php. Не помещайте секреты в argv: их могут увидеть история shell и список процессов; читайте секрет из защищённого файла, vault или stdin по политике окружения.

STDIN, STDOUT, STDERR и EOF: данные вместо браузера

STDIN, STDOUT и STDERR — заранее открытые streams CLI. Данные можно передать pipeline, полезный результат отправить в STDOUT, предупреждения — в STDERR, а успех обозначить exit code 0. fgets(STDIN) читает строку и возвращает false при EOF; file_get_contents("php://stdin") читает весь остаток и подходит только при известном лимите.

Одинаковый обработчик для файла и STDINСамостоятельный пример
<?php
declare(strict_types=1);

function streamLines($stream): Generator
{
    while (($line = fgets($stream)) !== false) {
        yield $line;
    }
}

function summarizeLines(iterable $lines): array
{
    $accepted = 0;
    $rejected = 0;
    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '') { continue; }
        $columns = str_getcsv($line, ',', '"', '');
        if (count($columns) !== 2 || !ctype_digit($columns[1])) {
            $rejected++;
            continue;
        }
        $accepted++;
    }
    return [$accepted, $rejected];
}

$input = fopen(__DIR__ . '/orders.csv', 'rb');
if ($input === false) { throw new RuntimeException('orders.csv не открыт'); }
[$accepted, $rejected] = summarizeLines(streamLines($input));
fclose($input);
echo "Принято: $accepted\nОтклонено: $rejected\n";
Ожидаемый результат
Принято: 2
Отклонено: 1

Выполненный опыт читает приложенный файл построчно: streamLines превращает resource в iterable Generator. В реальной команде summarizeLines(streamLines(STDIN)) обработает перенаправленные строки без загрузки всего файла в память.

Перенаправить три канала в оболочкеФрагмент или команда
# PowerShell
Get-Content .\orders.csv | php .\import.php
$ok = $LASTEXITCODE

# sh/bash
cat orders.csv | php import.php > accepted.txt 2> errors.log
status=$?

Pipeline и redirection принадлежат shell. Пример не исполняется verifier-ом PHP; он показывает, куда попадут stdout, stderr и exit code.

Интерактивная оболочка: исследовать, затем сохранить в файл

php -a запускает интерактивный режим. При наличии readline появляется полноценная interactive shell: prompt, история, tab completion, многострочные конструкции. Без readline сборка может показать только «Interactive mode enabled» и исполнять ввод построчно без тех же удобств. Проверьте php -m или extension_loaded("readline").

ПодходитНе подходит
Быстро проверить выражение, формат даты, сигнатуруХранить важный код только в истории.
Посмотреть var_dump небольшого значенияВставлять production secrets в общую историю терминала.
Исследовать объект через reflectionСчитать интерактивный опыт повторяемым тестом.

Настройки cli.prompt и cli.pager относятся к readline shell. #cli.prompt=… и #cli.pager=… меняют их внутри сеанса; точный набор meta-команд зависит от текущей сборки. Проверяемый результат переносите в PHP-файл и тест.

php -S: быстрый локальный HTTP-стенд с router.php

Development server запускается php -S 127.0.0.1:8000 -t public router.php. Если router возвращает false, сервер отдаёт существующий статический файл; иначе router формирует ответ. Он не читает .htaccess и не заменяет nginx/Apache/FPM. Привязывайте лабораторию к loopback, не выставляйте её в интернет.

Router для /health и статических файловПример для указанного окружения
<?php
declare(strict_types=1);

$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
if ($path !== '/' && is_file(__DIR__ . '/public' . $path)) {
    return false;
}
if ($path === '/health') {
    header('Content-Type: application/json; charset=UTF-8');
    echo json_encode(['status' => 'ok'], JSON_THROW_ON_ERROR);
    return true;
}
http_response_code(404);
header('Content-Type: text/plain; charset=UTF-8');
echo 'Not Found';
return true;
Ожидаемый результат
GET /health → HTTP 200 и {"status":"ok"}; существующий /app.css отдаётся сервером; неизвестный путь → HTTP 404 и Not Found.

Синтаксис проверен. Реальный HTTP lifecycle проверяется отдельным loopback-стендом; здесь не делается ложное утверждение о веб-сервере production.

CLI ini: сначала определить SAPI и binary, потом править файл

CLI читает свой набор ini. Команды php --ini, php -i и php -r "echo php_ini_loaded_file();" отвечают только за этот binary/SAPI. FPM проверяется через защищённый диагностический endpoint или конфигурацию pool, а не через терминал.

Директива CLIНазначение
cli_server.colorЦветной вывод встроенного development server.
cli.promptСтрока приглашения интерактивной readline shell.
cli.pagerКоманда pager для вывода interactive shell.
-cВыбрать файл/каталог ini для одного запуска.
-nЗапустить без php.ini, полезно для изоляции конфигурации.
-d name=valueПереопределить доступную директиву на время процесса.

Не копируйте CLI ini поверх FPM вслепую: у web и worker разные лимиты, extensions и модель угроз. Вместо этого храните осознанный общий слой и отдельные SAPI overrides, а диагностику прикладывайте вместе с PHP_BINARY, PHP_SAPI, php --ini и php -m.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.