Командная строка 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.