[英]Running a Zend Framework action from command line
我想從命令行運行Zend Framework操作來生成一些文件。 這是可能的,我需要對使用ZF的現有Web項目進行多少更改?
謝謝!
UPDATE
雖然解決方案#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中為Web界面定義了自己的路由,則可能需要在命令行模式下中和它們。
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
在這種情況下,將調用BackupController控制器中的cliAction方法。
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";
}
}
}
它實際上比你想象的要容易得多。 可以使用CLI腳本重用引導程序/應用程序組件和現有配置,同時避免在HTTP請求中調用的MVC堆棧和不必要的權重。 這是不使用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'));
然后,您可以像在MVC應用程序中一樣繼續使用ZF資源:
$db = $application->getBootstrap()->getResource('db');
$row = $db->fetchRow('SELECT * FROM something');
如果要將可配置參數添加到CLI腳本,請查看Zend_Console_Getopt
如果您發現您在MVC應用程序中也調用了公共代碼,請查看將其包裝在對象中並從MVC和命令行應用程序中調用該對象的方法。 這是一般的良好做法。
剛看到這個在我的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',
),
),
),
),
),
),
使用上面的配置,您可以在Application模塊下的IndexController.php中定義doCliAction。 從命令行運行它是蛋糕:
php index.php做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() );
}
}
如上所述,初始化錯誤可能是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
您需要實現更強大的過濾/轉義,但它是一個快速構建塊。 希望這可以幫助!
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中,注釋echo和die語句
public function assemble($userParams, $name = null, $reset = false, $encode = true) {
//echo "Not implemented\n";
}
一種選擇是,您可以通過對用於調用所需操作的URL執行wget來捏造它
你不能使用wget的-O選項來保存輸出。 但是wget顯然不是解決方案。 更喜歡使用CLI。
您可以像在命令行中一樣使用PHP。 如果您從PHP調用腳本並在腳本中設置操作,則可以運行您想要的任何內容。
真的很簡單。 它並不是真正的預期用途,但如果您願意,它就是如何工作的。
例如
php script.php
如果您的操作系統是Linux,則可以使用wget命令。 例如:
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
如果您不想保存輸出
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.