До этого момента мы с Вами знали, что PHP работает на сервере. Клиент обращается к серверу по протоколу HTTP с каким-либо запросом, запрос на сервере обрабатывается и формируется ответ. После этого клиенту снова по протоколу HTTP в ответе отдаётся сформированный ответ. Однако, если взять какой-нибудь более-менее продвинутый сайт, то мы увидим, что есть задачи, которые не решаются стандартным клиент-серверным путем. Например: поздравлять пользователей с днём рождения и дарить им скидку на какой-нибудь продукт. Для того, чтобы это сделать, нам придется обновлять раз в день php-скрипт в браузере, чтобы он выбирал пользователей, у которых сегодня ДР, затем создавал для них скидки, и отправлял им сообщения по почте. Согласитесь, неудобно это делать вручную и в браузере. Для таких случаев в PHP предусмотрен Command Line Interface (CLI) – интерфейс командной строки.
Продолжение урока будет доступно вам
после покупки курса PHP для профессионалов
«Bash? Беляш? Эммм… Что? Как? По-че-му?» — если именно эти слова произносил ваш внутренний голос, когда вы, начитавшись статей в интернете, решили с помощью Bash автоматизировать ту рутинную задачу, то эта статья для вас. И она ещё более для вас, если вы уже знаете PHP — сейчас вы узнаете также то, что PHP отлично подходит не только для разработки сайтов, но и для консольных приложений.
Предполагается, что вы используете Linux и знаете PHP не ниже начального уровня:
Что такое PHP CLI
Итак, вот как выглядит самое простое приложение на PHP:
Но его можно запустить не только через браузер, но и через консоль. Если вы разместим этот код в файле с названием hello_world.php :
Вывод будет весьма ожидаемым:
В консольных PHP приложениях (CLI) вы можете использовать всё то, что и в обычных PHP приложениях, например, записывать и читать файлы функциями file_put_contents и file_get_contents .
Получение аргументов из командной строки
Менее знакомыми для обычных PHP-разработчиков являются функции для работы с командой строкой.
Если вы хотите передать из командой строки какие-либо аргументы в свой скрипт:
…то прочитать их из PHP можно с помощью глобальной переменной $argv. В данном случае её содержимое будет выглядеть вот так:
Заметьте, что значением с индексом 0 всегда является имя запускаемого скрипта. В некоторых случаях для чтения списка аргументов также может быть удобна функция getopt.
Чтение пользовательского ввода
Функция readline создана для запроса пользовательского ввода и используется следующим образом:
Выполнение сторонних приложений
Но когда возможностей стандартной библиотеки PHP не хватает, на помощь приходит функция system: с её помощью можно вызывать сторонние приложения.
ZIP Service, Москва, можно удалённо, от 100 000 ₽
Если нам, например, нужно стереть с экрана весь предыдущий вывод, то из PHP мы сможем сделать это вот так:
Это выполнит команду clear , как будто вы сами ввели её в консоль.
Форматирование вывода
Конечно, вы не можете выводить HTML-теги функцией echo, как вы делали раньше, и надеяться на отформатированный вывод, но возможность задать базовое оформление всё же остается благодаря так называемым эскейп-последовательностям:
Сокращенное написание
Ура, теперь вы знаете, как делать настоящие консольные приложения на PHP! Но, согласитесь, писать каждый раз
не очень то весело и даже немножко грустненько.
Но и эту проблему можно решить, просто добавьте в начало файла #!/usr/bin/php , где /usr/bin/php является адресом вашего PHP интерпретатора.
Итоговый файл должен получиться примерно таким:
Если назвать его myapp (без расширения), то при условии, что вы находитесь в папке с файлом, запустить его можно будет вот так:
А чтобы запускать ваше консольное приложение из любой существующей, нескольких несуществующих и одной невероятной папки, достаточно просто перенести его в каталог /usr/bin. Например, вот так:
Небольшой пример реального кода для закрепления знаний: FastAdminer — консольное PHP приложение, в котором используется всё описанное в статье.
Начиная с версии 4.3, РНР поддерживает новый SAPI -тип (Server Application Programming Interface) под названием CLI , что означает Command Line Interface . Как следует из названия, главной задачей этого SAPI -типа является разработка оболочки/shell (или рабочего стола) приложений с помощью РНР. Имеются весьма небольшие отличия CLI SAPI от других SAPI , которые будут далее рассмотрены в этой главе.
CLI SAPI был выпущен в первый раз с PHP 4.2.0 , но тогда это был эксперимент, и нужно было явно включать его командой —enable-cli при запуске ./configure . Начиная с PHP 4.3.0 , CLI SAPI больше не является экспериментальным и всегда встроен и устанавливается как двоичный исполняемый файл php (называется php.exe в Windows).
Существенные отличия CLI SAPI от других SAPI :
В отличие от CGI SAPI , никакие шапки/headers не записываются в вывод.
Хотя в CGI SAPI имеется способ подавления HTTP-шапок, эквивалентного переключателя для их включения в CLI SAPI нет.
Имеются определённые директивы php.ini , которые переопределены в CLI SAPI , поскольку они не имеют смысла в среде окружения оболочки:
Таблица 24-1. Переопределение php.ini -директив
Директива | CLI SAPI- значение по умолчанию | Комментарий |
---|---|---|
html_errors | FALSE | Бывает довольно сложно прочитать в оболочке сообщение об ошибке, наполненное всеми этими бессмысленными HTML -тэгами, поэтому по умолчанию значение этой директивы FALSE . |
implicit_flush | TRUE | Желательно, чтобы любой вывод из print() , echo() и компании немедленно записывался в вывод, а не отправлялся в какой-нибудь буфер. Вы всё ещё можете пользоваться буферизацией вывода, если хотите поработать со стандартным выводом. |
max_execution_time | 0 (unlimited) | Из-за бесконечно больших возможностей использования PHP в среде окружения оболочки, максимальное время выполнения не ограничено. В то время как приложения, написанные для web, выполняются в течение долей секунды, приложения оболочки пытаются занять для своего выполнения максимальное время. |
register_argc_argv | TRUE | Глобальные переменные PHP $argc (количество аргументов, передаваемых приложению) и $argv (массив текущих аргументов) всегда регистрируются и заполняются соответствующими значениями при использовании CLI SAPI . |
Примечание: Эти директивы не могут быть инициализированы другим значением из файла конфигурации php.ini или специального файла (если специфицирован). Это является некоторым ограничением, поскольку эти значения по умолчанию применяются после разбора всех файлов конфигурации. Однако их значение может быть изменено на этапе прогона программы (что не имеет смысла для всех других директив, например, для register_argc_argv).
Легче работать в среде оболочки, когда определены следующие константы:
Таблица 24-2. Специфические CLI-константы
Константа | Описание |
---|---|
STDIN | Уже открытый поток в stdin . Она хранит открывшего её |
STDOUT | Уже открытый поток в stdout . Она хранит открывшего её |
STDERR | Уже открытый поток в stdout . Она хранит открывшего её |
Имея всё это, вы не должны, например, самостоятельно открывать поток для stderr , а просто используете константу вместо ресурса потока:
Вам не нужно явно закрывать эти потоки, это делается РНР автоматически.
CLI SAPI не изменяет текущую директорию на директорию исполняемого скрипта!
Пример, показывающий отличие CGI SAPI :
Когда используется CGI -версия, на выходе будет:
Это ясно показывает, что PHP изменяет свою текущую директорию на директорию исполняемого скрипта.
Использование CLI SAPI даёт:
Это даёт большую гибкость при написании утилит командной строки на PHP .
Примечание: CGI SAPI поддерживает поведение CLI SAPI с помощью ключа -C при запуске из командной строки.
Список опций командной строки исполняемого файла PHP может быть получен в любое время путём запуска PHP с ключом -h :
CLI SAPI имеет три разных способа получения PHP -кода, который нужно выполнить:
Сказать PHP выполнить определённый файл.
Оба способа (с/без использования переключателя -f ) выполняют данный файл my_script.php . Вы можете выбрать для выполнения любой файл, названия ваших файлов скриптов PHP не обязаны заканчиваться расширением .php , а могут иметь любое имя или расширение.
Передать PHP код для выполнения непосредственно из командной строки.
Особого внимания требует замена переменных оболочки и использование кавычек.
Примечание: Просмотрите пример внимательно, нет начальных и конечных тэгов! Переключателю -r они просто не нужны. Использование их в данном случае приведёт к ошибке разборщика.
Предоставить PHP -код для выполнения через стандартный ввод ( stdin ).
Это позволяет динамически создавать PHP -код и передавать его экзешнику, как показано в данном (надуманном) примере:
Вы не можете комбинировать эти три способа при выполнении кода.
Как и в любом приложении оболочки, не только сам PHP , но и ваши скрипты PHP также принимают аргументы. Количество передаваемых в скрипт аргументов в РНР не ограничивается (оболочка имеет ограничение на количество передаваемых символов).
Аргументы, передаваемые в ваш скрипт, доступны через глобальный массив $argv . Нулевой индекс всегда содержит имя скрипта (которое является символом — в случае, когда PHP -код приходит со стандартного ввода или с использованием ключа командной строки -r ).
Вторая регистрируемая глобальная переменная это $argc , которая содержит количество элементов в массиве $argv (а не количество аргументов, передаваемых в скрипт).
Если аргументы, которые вы хотите передать в скрипт, не начинаются с символа дефиса (-) , ничего специально наблюдать не надо. Передача в скрипт аргумента, начинающегося с — , создаст проблемы, поскольку PHP думает, что должен сам их обработать. Чтобы предотвратить это, используйте в качестве сепаратора аргументов списка — . После того как аргумент будет разобран PHP , каждый последующий аргумент передаётся в ваш скрипт без изменений/не разобранным.
Однако, вот другой способ использования PHP для скриптинга оболочки. Вы можете написать скрипт, первая строка которого начинается с #!/usr/bin/php , а затем идёт нормальный PHP -код, содержащийся между начальным и конечным тэгами PHP , и соответствующим образом устанавливаются атрибуты выполнения файла. Таким способом он может быть исполнен как нормальный скрипт оболочки или perl:
Приняв, что файл называется test и находится в текущей директории, мы можем выполнить:
Как вы видите, ничего особо не нужно делать при передаче параметров в скрипт, который начинается с — .
Таблица 24-3. Опции командной строки
Опция | Описание |
---|---|
-s | |
-c | |
-a | |
-e | |
-i | Эта опция командной строки вызывает phpinfo() и печатает на вывод результаты. Если PHP не работает правильно, советуем выполнить php -i и посмотреть, выводятся ли сообщения об ошибке до или вместо таблиц информации. Имейте в виду, что вывод будет на HTML и, следовательно довольно сумбурным. |
-r | |
-h | С помощью данной опции вы можете получить информацию о действующем списке опций командной строки и небольшое описание их работы. |
Исполняемый файл PHP может быть использован для запуска PHP-скриптов абсолютно независимо от web-сервера.
Если вы работаете под Unix, вы должны добавлять специальную первую строчку в ваши PHP-скрипты и делать их исполняемыми, чтобы система знала, какая программа должна выполнять эти скрипты.
Под Windows вы можете ассоциировать php.exe с опцией двойного щелчка по файлам .php либо сделать batch-файл (.bat) для запуска скрипта через PHP. Строка, добавленная в начало скрипта для работы под Unix, не помешает под Windows, поэтому вы можете писать таким образом межплатформенные программы. Ниже дан пример простой РНР-программы для выполнения из командной строки.
Пример 24-1. Скрипт, предназначенный для запуска из командной строки (script.php) |
Здесь мы используем специальную первую строку для указания на то, что этот файл должен быть запущен в PHP. Здесь мы работаем с CLI-версией, поэтому не выполняется вывод HTTP-шапок/header. Имеются две переменные, которые вы можете использовать при написании РНР-приложений для командной строки: $argc и $argv . Первая — это количество аргументов плюс 1 (имя запущенного скрипта). Вторая — это массив аргументов, начиная с имени скрипта с индексом ноль ( $argv[0] ).
Мы проверяем, имеется ли менее или более одного аргумента. Также, если аргумент был —help , -help , -h или -? , мы печатаем help-сообщение, выводя имя скрипта динамически. Если мы получили какой-либо другой аргумент, мы выводим его (echo).
Если вы хотите выполнить вышеприведённый скрипт под Unix, вам необходимо сделать его executable и просто вызвать как script.php echothis или script.php -h . Под Windows вы можете создать batch-файл для выполнения этой задачи:
Пример 24-2. Пакетный/Batch-файл для запуска PHP-скрипта в командной строке (script.bat) |
Приняв, что вы назвали программу script.php и что ваш php.exe находится в c:phpphp.exe , этот batch-файл запустит её с добавленными вами опциями: script.bat echothis или script.bat -h .
См. также в документации по расширению Readline о функциях, которые можно использовать для усовершенствования вашего РНР-приложения для командной строки.