Командная строка Yii - Как инициализировать все мое веб-приложение и вызывать другие действия контроллера через yiic?

Обновление - я смог решить эту проблему, добавив 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);

У меня есть простая yiic-команда в protected/commands/dBManagerCommand.php, которую я могу запустить из командной строки:

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 (игнорировать цвета кода)

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 ниже, я собираюсь вставить этот ответ здесь, потому что поле комментария недостаточно длинное.

Во-первых, я бы не стал предварительно загружать все контроллеры для веб-интерфейса, но для этого он решил проблему и работает нормально. Метод import первоначально принимает запросы через контроллер, но затем вызывает методы модели, где это уместно, для логики и операций на уровне базы данных и файловой системы. (И да, у меня есть другие классы моделей импорта, выделенные для этой цели, в основном из-за утечек памяти в Yii, связанных с поведением).

Идея, что никто не должен делать какую-либо логику в контроллере, просто ошибочна, imo. В этом случае я решил сделать методы импорта в контроллерах, которые выполняют некоторую логику фильтрации входных данных, потому что существует большое количество входных данных, которые пользователь (человек или cron) должен представить, и это должно произойти, прежде чем мы доберемся до задача разбора файлов в БД. Этот метод импорта контроллера анализирует файлы на основе пользовательского ввода и передает предварительно отфильтрованные данные в метод модели. Я решил сделать это, потому что входные данные файла - фактически ненадежный пользовательский ввод, и мне нужно было выполнить некоторую предварительную обработку на основе параметров пользовательского запроса. Да, вы можете сделать это в методе модели, но это приведет либо к обработке данных запроса в модели, либо к передаче большого количества аргументов и данных, что создает трудности и увеличивает использование памяти.

1 ответ

Обычно такие проблемы являются признаком неоптимальной архитектуры. Я бы сказал, что это одна из наиболее частых ошибок разработчиков, когда в контроллере MVC слишком много кода, связанного с моделью.

Предположительно, ваш код будет выполнять пакетный импорт данных из файла (или другого источника данных). Это образцовое задание! Таким образом, вы должны написать метод в классе связанной модели, например, public static import($filename), Внутри этого метода вы также должны избегать жесткой связи с другими компонентами (например, Yii::app()->user который не доступен в CLI).

Если это более сложная задача, вы даже можете написать специальный класс для вашего импорта. Этот класс может представлять задание на импорт и предоставлять такие методы, как import() или же getError() получить статус ошибки импорта.

Такое разделение классов значительно увеличивает возможность повторного использования: теперь вы можете использовать этот метод модели или класс импорта как из действия вашего контроллера, так и из вашей команды CLI.

Другие вопросы по тегам