В документации по фреймворку webasyst описано, как создавать консольные команды, то есть команды которые можно вызывать из консоли, без участия веб-сервера.
Статья справки размещена здесь: www.webasyst.ru/developers/docs/features/cli/
Минус описанного в ней метода в том, что скрипт придётся помещать в папку wa-apps/[APP_ID]/lib/cli, то есть фактически в папку с приложением класть свой код, что приведёт в конечном итоге к бардаку и хаосу.
Также, в справочной системе есть статья о плагинах, где написано, что плагины тоже могут иметь консольные команды.
вот эта статья: www.webasyst.ru/help/98/shop-script-5-plugin-development/
Однако, как совместить консольные скрипты и плагины — не сказано.
Поскольку ждать ответа от техподдержки можно долго, я предпочел самостоятельно расковырять исходный код, и найти как поместить консольный скрипт в свой плагин.
Предположим, что у вас уже есть свой плагин, записанный в соответствующее приложение (в моём случае это shop).
Плагин может быть совсем пустым, но он должен «восприниматься» приложением, и быть включённым в настройках.
Я пишу плагин для синхронизации базы товаров с товарной номенклатурой поставщика, который предоставляет доступ к своей базе данных, поэтому плагин называется GoodsSyncronizerPlugin, и лежит он в папке /wa-apps/shop/plugins/goodsSync/
Для того, чтобы заработал мой консольный скрипт понадобилось проделать следующее:
1. Создать папку /wa-apps/shop/plugins/goodsSync/lib/cli — на самом деле, это не обязательно, но чтобы придерживаться общей концепции фреймворка, лучше складывать файлы по их назначению в соответствующие папки. В действительности, при загрузке ваших файлов классов, система ищет их рекурсивно в папках /wa-apps/[APP_ID]/lib, /wa-apps/[APP_ID]/plugins и /wa-apps/[APP_ID]/api, так что где бы вы ни положили ваши файлы — лишь бы они были где-то внутри этих папок, в нашем случае — внутри папки с плагином.
2. Создать класс, наследованный от waCliController shopGoodsSyncronizerCronCli, причём имя класса должно состоять из: [APP_ID][ВашеНазвание]Cli, где «ваше название» по возможности должно быть однозначным, или даже включать в себя имя плагина, в противном случае, оно может совпасть с другим таким-же названием класса чужого плагина. [APP_ID] — это имя вашего плагина, а «Cli» — обязательное окончание (Слово Cron не обязательно, оно является частью моего название, потому что мне показалось правильным его вписать).
Имя файла в данном случае: shopGoodsSyncronizerCron.cli.php, то есть оно строится по примерно такой же схеме, а именно: [APP_ID][Ваше название].cli.php
3. Прописать в классе единственно необходимую функцию execute(), а в ней, для проверки вписать что-то для проверки работоспособности. Например:
<?php class shopGoodsSyncronizerCronCli extends waCliController { public function execute() { die("Выполнился скрипт GoodsSyncronizerCron") } } |
Для проверки вызываем скрипт из консоли:
$ php /var/www/localsite/public_html/cli.php shop GoodsSyncronizerCron |
После выполнения должна вывестись наша строка «Выполнился скрипт GoodsSyncronizerCron»
Параметры:
При вызове скрипта из консоли можно передавать ему параметры, которые станут доступны в массиве, возвращаемом waRequest::param() (вызывать без параметров чтобы получить весь массив)
1) Параметры имеющие только значения:
После имени класса консольной команды просто указываем слова, каждое из которых станет значением параметра. Ключи параметров будут числовыми.
Например, при выполнении:
$ php /var/www/localsite/public_html/cli.php shop GoodsSyncronizerCron the answer is 42 |
Функция waRequest::param() вёрнёт вам:
array( 0 => "the", 1 => "answer", 2 => "is", 3 => "42" )
2) Параметры ключ-значение:
При выполнении команды:
$ php /var/www/localsite/public_html/cli.php shop GoodsSyncronizerCron --answer 42 -question unknown |
Функция waRequest::param() вёрнёт вам:
array( "answer" => "42", "questiong" => "unknown" )
(При этом, параметр, означающий ключ, должен начинаться с 1 или 2-х минусов.)
3) Комбинированные параметры (и то и другое):
Оба метода можно свободно комбинировать:
При выполнении команды:
$ php /var/www/localsite/public_html/cli.php shop GoodsSyncronizerCron --answer 42 and question unknown |
Функция waRequest::param() вёрнёт вам:
array( "answer" => "42", 0 => "and", 1 => "question", 2 => "unknown" )
Определённо, что параметры задаваемые через ключ-значение удобнее простых параметров тем, что к ним можно обращаться прямо по ключу, например так:
echo waRequest::param("answer"); |
Параметры же с числовыми ключами — придётся искать через array_search или in_array
Дополнительно: отладка cli с помощью xdebug
Я привык пользоваться удобными инструментами разработки, вколючающими Netbeans IDE и Xdebug для отладки скриптов на PHP. Но консольный скрипт cli.php не запускается из браузера, сообщая «Run from CLI only!».
Для того, чтобы отлаживать мои консольные скрипты в браузере (ведь для отладки через XDebug в консоли придётся полностью менять настройки Netbeans (если такая его настройка вообще возможна)) я подправил файл wa-system/cli.php, чтобы он больше не ругался на то что запущен из браузера.
Вот какие строчки не давали этому скрипту запускаться где-то кроме консоли:
if (PHP_SAPI !== 'cli') { die('Run from CLI only!'); } |
Заменим этот блок на вот такой:
if (PHP_SAPI !== 'cli') { // Здесь должно быть указано имя вашего локального домена if ($_SERVER['SERVER_NAME']=='localsite') { //Если не переданы важные параметры запуска - запросим их if (!isset($_GET['app']) || !isset($_GET['class'])) { die("<form>" . "APP_ID:<input type='text' name='app'><br>" . "Class:<input type='text' name='class'><br>" . "Parameters:<input type='text' name='params'>(divided by space)<br>" . "<input type='submit'></form>"); } else { //получаем параметры из поля 'params' и разбиваем его на отдельные параметры пробелами $params = isset($_GET['params']) ? explode(" ", $_GET['params']) : array(); //Формируем "фиальшивые" параметры командной строки $_SERVER['argv'] = array_merge( array("cli.php", $_GET['app'], $_GET['class']), $params); //откроем стандартный вывод чтобы все ошибки попадали не в лог сервера //а прямо в выдачу браузера define("STDERR", fopen("php://output","w")); } $_SERVER['argc']=count($_SERVER['argv']); } else { //Сервер оказался не локальный, всё-таки умраем die('Run from CLI only!'); } } |
Теперь, при открытии в браузере адреса http://localsite/cli.php вы увидите примерно это:
В поле APP_ID нужно ввести ваше приложение, например «shop», а в поле class — название класса, в моём случае это GoodsSyncronizerCron.
В поле Parameters нужно ввести все параметры, которые нужно передать в вашу функцию run() разделяя их пробелами. При вызове run() массив этих параметров будет передан в параметре $params.
P.S. Конечно, ориентация на имя локального веб-сервера — не самое лучшее решение, и идеально было бы использовать системную настройку debug (т.е., если включена отладка, то даём запустить скрипт в браузере, а если нет — то нет), но изменение скрипта специально сделано «на поверхности» без влезания в дальнейшую логику, которая собственно загружает основной скрипт приложения, и из него-то уже и можно узнать, идёт ли отладка (с помощью вызова isDebug()).
Оставить комментарий