【问题标题】:Yii Command line - How to initialize my entire web app and call other controller actions via yiic?Yii 命令行 - 如何初始化我的整个 Web 应用程序并通过 yiic 调用其他控制器操作?
【发布时间】:2013-07-16 14:51:24
【问题描述】:

更新 - 我可以通过像这样将 application.controllers.* 添加到 config/console.php 来解决这个问题:

'import'=>array(
        'application.models.*',
        'application.components.*',
        'application.controllers.*',
        'application.extensions.CAdvancedArBehavior',
        'application.extensions.eUploadedImage.*',
       ),

然后像这样在 cli 命令中调用操作:

$myCtrl=new CopyNumberNewSegController(NULL);
$myCtrl->actionBatchImport($libraries,$action);

我在 protected/commands/dBManagerCommand.php 中有一个简单的 yiic 命令,可以从命令行运行:

class DBManagerCommand extends CConsoleCommand
{
    public $verbose=false;
    public $divider="--------------------------------------------------------------------------\n";
    public $title="DB Manager Command\n";
    public function actionImportAnalysis($libraries=false,$action='incomplete') {
        echo $this->divider;
        echo $this->title;
        echo $this->divider;
        echo 'Importing '.$action ." analysis data from file system...\n";
        echo $this->divider;

        switch ($action) {

            case 'incomplete':

                CopyNumberNewSegController::batchImport($libraries,$action);


                break;
        }

        return 0;
    }
}

运行它会产生以下错误。显然它找不到我的其他控制器。我想在我的应用程序的其余部分中从现有控制器运行方法。这是从 bash shell 运行的(忽略代码颜色)

yiic dbmanager importAnalysis --action=incomplete
--------------------------------------------------------------------------
DB Manager Command
--------------------------------------------------------------------------
Importing incomplete analysis from file system...
--------------------------------------------------------------------------
PHP Error[2]: include(CopyNumberNewSegController.php): failed to open stream: No such file or directory
    in file /var/www/html/mioncoseq/pub/framework/YiiBase.php at line 418
#0 /var/www/html/mioncoseq/pub/framework/YiiBase.php(418): autoload()
#1 unknown(0): autoload()
#2 /var/www/html/mioncoseq/pub/protected/commands/dBManagerCommand.php(21): spl_autoload_call()
#3 unknown(0): DBManagerCommand->actionImportAnalysis()
#4 /var/www/html/mioncoseq/pub/framework/console/CConsoleCommand.php(141): ReflectionMethod->invokeArgs()
#5 /var/www/html/mioncoseq/pub/framework/console/CConsoleCommandRunner.php(65): DBManagerCommand->run()
#6 /var/www/html/mioncoseq/pub/framework/console/CConsoleApplication.php(91): CConsoleCommandRunner->run()
#7 /var/www/html/mioncoseq/pub/framework/base/CApplication.php(162): CConsoleApplication->processRequest()
#8 /var/www/html/mioncoseq/pub/framework/yiic.php(33): CConsoleApplication->run()
#9 /var/www/html/mioncoseq/pub/protected/yiic.php(7): require_once()
#10 /var/www/html/mioncoseq/pub/protected/yiic(4): require_once()

那么我该如何加载这些控制器方法呢?我确信有一种适当的方法可以初始化我的整个应用程序,而无需尝试手动包含这些控制器文件。

谢谢大家!


针对下面关于滥用MVC架构的批评,我将在此处粘贴此回复,因为评论字段不够长。

首先,我不会为 Web 界面预加载所有控制器,但为此它解决了问题并且工作正常。导入方法最初通过控制器接受请求,然后在适合数据库和文件系统级逻辑和操作的情况下调用模型方法。 (是的,我确实有其他专门用于此目的的导入模型类,主要是因为 Yii 中与行为相关的内存泄漏)。

不应该在控制器中执行任何逻辑的想法是错误的,imo。在这种情况下,我选择在执行某些输入过滤逻辑的控制器中创建导入方法,因为用户(人或 cron)需要提交大量输入,这需要在我们到达之前发生将文件解析到数据库中的任务。此控制器导入方法根据用户输入解析文件并将预过滤的数据传递给模型方法。我选择这样做是因为文件输入数据实际上是不受信任的用户输入,我需要根据用户请求参数进行一些预处理。是的,您可以在模型方法中执行此操作,但这会导致在模型中处理请求数据,或者传递大量参数和数据,这很麻烦并且会增加内存使用量。

【问题讨论】:

    标签: php command-line yii yiic


    【解决方案1】:

    通常,此类问题表明架构不理想。我想说,在使用 MVC 框架时,控制器中有太多与模型相关的代码是开发人员最常见的错误之一。

    假设您的代码将从文件(或其他数据源)批量导入数据。这是一个模型任务!所以你应该在相关的模型类中编写一个方法,例如public static import($filename)。在该方法中,您还应该避免与其他组件紧密耦合(例如,Yii::app()->user 在 CLI 中不可用)。

    如果这是一项更复杂的任务,您甚至可以为您的导入编写一个专用类。该类可以表示一个导入作业,并提供诸如import()getError() 之类的方法来获取导入的错误状态。

    像这样解耦类大大提高了可重用性:您现在可以使用该模型方法或从控制器操作和 CLI 命令两者中导入类。

    【讨论】:

    • 对于从 cron 作业运行的某些东西的后端目的,我认为加载所有控制器没有问题。它解决了问题。
    • Yii 中的控制器用于处理 Web 请求。他们将模型连接到视图。它们并不是为了清理输入。当您调用 setAttributes()validate() 时,模型中会发生这种情况。
    • 在插入之前在模型中进行验证,我知道,但是在将请求传递给模型进行插入之前,我完全可以在控制器中预处理请求或输入数据。控制器不进行数据库插入验证,它基于请求参数和其他设置(例如拆分 csv 行)进行预处理。从 yiic 执行此操作的理由是,我希望 cron 充当用户并以用户身份触发请求操作,而无需通过 curl 访问 URL,需要身份验证。这是迄今为止最简单的解决方案。
    猜你喜欢
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2012-01-19
    • 2010-11-28
    • 1970-01-01
    • 2019-11-10
    相关资源
    最近更新 更多