从命令行运行 Zend 框架操作

2022-08-30 09:16:17

我想运行Zend框架操作以从命令行生成一些文件。这是否可能,我需要对使用 ZF 的现有 Web 项目进行多少更改?

谢谢!


答案 1

更新

如果您愿意,可以从 https://github.com/akond/zf-cli 中为采埃孚 1.12 调整所有这些代码。

虽然解决方案#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');
    }
}

在错误控制器中.php

function cliAction ()
{
    $this->_helper->viewRenderer->setNoRender (true);

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

答案 2

这实际上比你想象的要容易得多。引导/应用程序组件和现有配置可以与 CLI 脚本一起重用,同时避免在 HTTP 请求中调用的 MVC 堆栈和不必要的权重。这是不使用 wget 的一个优点。

像启动公共索引一样启动脚本.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 应用程序中一样:

$db = $application->getBootstrap()->getResource('db');

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

如果您希望向 CLI 脚本添加可配置的参数,请查看Zend_Console_Getopt

如果发现有在 MVC 应用程序中调用的通用代码,请考虑将其包装在对象中,并从 MVC 和命令行应用程序调用该对象的方法。这是一般的良好做法。


推荐