Запуск действия Zend Framework из командной строки

Я хотел бы запустить действие Zend Framework для создания некоторых файлов из командной строки. Является ли это возможным и сколько изменений мне необходимо внести в мой существующий веб-проект, который использует ZF?

Благодаря!

На самом деле это намного проще, чем вы думаете. Компоненты bootstrap / application и ваши существующие конфигурации могут быть повторно использованы с помощью сценариев CLI, избегая стека MVC и ненужного веса, который вызывается в HTTP-запросе. Это одно из преимуществ использования wget.

Начните свой скрипт, как ваш общедоступный index.php:

<?php // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); require_once 'Zend/Application.php'; $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/config.php' ); //only load resources we need for script, in this case db and mail $application->getBootstrap()->bootstrap(array('db', 'mail')); 

Затем вы можете использовать ресурсы ZF так же, как и в приложении MVC:

 $db = $application->getBootstrap()->getResource('db'); $row = $db->fetchRow('SELECT * FROM something'); 

Если вы хотите добавить настраиваемые аргументы в свой CLI-скрипт, взгляните на Zend_Console_Getopt

Если вы обнаружите, что у вас есть общий код, который вы также вызываете в приложениях MVC, посмотрите на его обертку в объекте и вызовите методы этого объекта как из MVC, так и из приложений командной строки. Это общая хорошая практика.

ОБНОВИТЬ

Вы можете использовать весь этот код для ZF 1.12 от https://github.com/akond/zf-cli, если хотите.

Хотя решение № 1 в порядке, иногда вам нужно что-то более сложное. Особенно, если вы ожидаете иметь не один сценарий CLI. Если вы позволите мне, я предлагаю другое решение.

Прежде всего, в вашем Bootstrap.php

 protected function _initRouter () { if (PHP_SAPI == 'cli') { $this->bootstrap ('frontcontroller'); $front = $this->getResource('frontcontroller'); $front->setRouter (new Application_Router_Cli ()); $front->setRequest (new Zend_Controller_Request_Simple ()); } } 

Этот метод лишит диспетчерский контроль от маршрутизатора по умолчанию в пользу нашего собственного маршрутизатора Application_Router_Cli.

Кстати, если вы определили свои собственные маршруты в _initRoutes для своего веб-интерфейса, вы, вероятно, захотите их нейтрализовать в режиме командной строки.

 protected function _initRoutes () { $router = Zend_Controller_Front::getInstance ()->getRouter (); if ($router instanceof Zend_Controller_Router_Rewrite) { // put your web-interface routes here, so they do not interfere } } 

Класс Application_Router_Cli (предположим, что вы включили автозагрузку для префикса приложения) может выглядеть так:

 class Application_Router_Cli extends Zend_Controller_Router_Abstract { public function route (Zend_Controller_Request_Abstract $dispatcher) { $getopt = new Zend_Console_Getopt (array ()); $arguments = $getopt->getRemainingArgs (); if ($arguments) { $command = array_shift ($arguments); if (! preg_match ('~\W~', $command)) { $dispatcher->setControllerName ($command); $dispatcher->setActionName ('cli'); unset ($_SERVER ['argv'] [1]); return $dispatcher; } echo "Invalid command.\n", exit; } echo "No command given.\n", exit; } public function assemble ($userParams, $name = null, $reset = false, $encode = true) { echo "Not implemented\n", exit; } } 

Теперь вы можете просто запустить свое приложение, выполнив

 php index.php backup 

В этом случае будет вызван метод cliAction в контроллере BackupController.

 class BackupController extends Zend_Controller_Action { function cliAction () { print "I'm here.\n"; } } 

Вы можете даже пойти дальше и изменить класс Application_Router_Cli, чтобы каждый раз не выполнялось действие «cli», а то, что пользователь выбрал с помощью дополнительного параметра.

И последнее. Определите настраиваемый обработчик ошибок для интерфейса командной строки, чтобы вы не увидели какой-либо код html на вашем экране.

В Bootstrap.php

 protected function _initError () { $error = $frontcontroller->getPlugin ('Zend_Controller_Plugin_ErrorHandler'); $error->setErrorHandlerController ('index'); if (PHP_SAPI == 'cli') { $error->setErrorHandlerController ('error'); $error->setErrorHandlerAction ('cli'); } } 

В ErrorController.php

 function cliAction () { $this->_helper->viewRenderer->setNoRender (true); foreach ($this->_getParam ('error_handler') as $error) { if ($error instanceof Exception) { print $error->getMessage () . "\n"; } } } 

Просто увидели, как этот человек помечается в моем CP. Если вы наткнулись на этот пост и используете ZF2, ему стало намного проще. Просто отредактируйте маршруты module.config.php следующим образом:

 /** * Router */ 'router' => array( 'routes' => array( // .. these are your normal web routes, look further down ), ), /** * Console Routes */ 'console' => array( 'router' => array( 'routes' => array( /* Sample Route */ 'do-cli' => array( 'options' => array( 'route' => 'do cli', 'defaults' => array( 'controller' => 'Application\Controller\Index', 'action' => 'do-cli', ), ), ), ), ), ), 

Используя приведенную выше конфигурацию, вы должны определить doCliAction в вашем IndexController.php в своем приложении. Запуск это торт, из командной строки:

php index.php do cli

Готово! Путь более плавный.

Решение akond выше находится на лучшем треке, но есть некоторые тонкости, которые могут его сценарий не работать в вашей среде. Рассмотрите эти настройки к его ответу:

Bootstrap.php

 protected function _initRouter() { if( PHP_SAPI == 'cli' ) { $this->bootstrap( 'FrontController' ); $front = $this->getResource( 'FrontController' ); $front->setParam('disableOutputBuffering', true); $front->setRouter( new Application_Router_Cli() ); $front->setRequest( new Zend_Controller_Request_Simple() ); } } 

Ошибка Init, вероятно, будет barf, как написано выше, обработчик ошибок, вероятно, еще не создан, если вы не изменили конфигурацию по умолчанию.

 protected function _initError () { $this->bootstrap( 'FrontController' ); $front = $this->getResource( 'FrontController' ); $front->registerPlugin( new Zend_Controller_Plugin_ErrorHandler() ); $error = $front->getPlugin ('Zend_Controller_Plugin_ErrorHandler'); $error->setErrorHandlerController('index'); if (PHP_SAPI == 'cli') { $error->setErrorHandlerController ('error'); $error->setErrorHandlerAction ('cli'); } } 

Вероятно, вы также захотите выполнить несколько команд из командной строки, вот пример:

 class Application_Router_Cli extends Zend_Controller_Router_Abstract { public function route (Zend_Controller_Request_Abstract $dispatcher) { $getopt = new Zend_Console_Getopt (array ()); $arguments = $getopt->getRemainingArgs(); if ($arguments) { $command = array_shift( $arguments ); $action = array_shift( $arguments ); if(!preg_match ('~\W~', $command) ) { $dispatcher->setControllerName( $command ); $dispatcher->setActionName( $action ); $dispatcher->setParams( $arguments ); return $dispatcher; } echo "Invalid command.\n", exit; } echo "No command given.\n", exit; } public function assemble ($userParams, $name = null, $reset = false, $encode = true) { echo "Not implemented\n", exit; } } 

Наконец, в вашем контроллере действие, которое вы вызываете, использует параметры, которые были потеряны путем удаления контроллера и действия с помощью маршрутизатора CLI:

 public function echoAction() { // disable rendering as required $database_name = $this->getRequest()->getParam(0); $udata = array(); if( ($udata = $this->getRequest()->getParam( 1 )) ) $udata = explode( ",", $udata ); echo $database_name; var_dump( $udata ); } 

Затем вы можете вызвать команду CLI с помощью:

 php index.php Controller Action .... 

Например, как указано выше:

 php index.php Controller echo database123 this,becomes,an,array 

Вы захотите реализовать более надежную фильтрацию / экранирование, но это быстрый строительный блок. Надеюсь это поможет!

Один из вариантов заключается в том, что вы можете выманить его, выполнив wget по URL-адресу, который используется для вызова желаемого действия

Вы не можете использовать опцию «o» для сохранения вывода. Но wget явно НЕ является решением. Предпочитаете вместо этого использовать CLI.

Идея akond отлично работает, за исключением исключения ошибки, которое не отображается контроллером ошибок.

 public function cliAction() { $this->_helper->layout->disableLayout(); $this->_helper->viewRenderer->setNoRender(true); foreach ($this->_getParam('error_handler') as $error) { if ($error instanceof Exception) { print "cli-error: " . $error->getMessage() . "\n"; } } } 

и в Application_Router_Cli комментировать off echo and die statement

 public function assemble($userParams, $name = null, $reset = false, $encode = true) { //echo "Not implemented\n"; } 

Вы можете просто использовать PHP, как обычно из командной строки. Если вы вызываете скрипт из PHP и задаете действие в своем скрипте, вы можете запустить все, что захотите.

Это было бы очень просто. На самом деле это не предполагаемое использование, но так оно и могло работать, если бы вы этого хотели.

Например

  php script.php 

Читайте здесь: http://php.net/manual/en/features.commandline.php

Вы можете использовать команду wget, если ваша ОС – Linux. Например:

 wget http://example.com/controller/action 

См. http://linux.about.com/od/commands/l/blcmdl1_wget.htm

ОБНОВИТЬ:

Вы можете написать простой скрипт bash следующим образом:

 if wget http://example.com/controller/action echo "Hello World!" > /home/wasdownloaded.txt else "crap, wget timed out, let's remove the file." rm /home/wasdownloaded.txt fi 

Тогда вы можете сделать в PHP:

 if (true === file_exists('/home/wasdownloaded.txt') { // to check that the } 

Надеюсь это поможет.

Я использовал команду wget

wget http://example.com/module/controller/action -O /dev/null

-O /dev/null если вы не хотите сохранять вывод