Yii2 - получение ошибок при вызове веб-контроллера с контроллера консоли - PullRequest
0 голосов
/ 31 мая 2018

Я работаю над yii2.У меня в контроллере есть действие create с именем MeterpingController.

class MeterpingController extends Controller
{
     public function beforeAction($action)
    {

    if ($action->id == 'create') {
        $this->enableCsrfValidation = false;
    }

    return parent::beforeAction($action);

   }

   public function actionCreate()
   {
      foreach ($record as $item){

        // var_dump($item->MSN);
         $date_time = str_replace('T', ' ', $item->PingDateTime);
        if($this->isSaved($item->MSN))
        {
           // return true;
        }
        else if($this->isVerified($item->MSN))
        {
            // return true;
        }
        else if($this->ogpCreated($item->MSN,$date_time))
        {
            $m = new MeterPing;
            $m ->load(Yii::$app->request->post());
            $m->start_date_time = str_replace('T', ' ', $start_time);
            $m->end_date_time = str_replace('T', ' ', $end_time);

           $m->meter_msn = $item->MSN;
           $m->meter_id = Meters::msnmapToid($m->meter_msn);
           $m->meter_type = Meters::mType($m->meter_msn);
           $m->sub_div_code = Ogpdetail::msnTosubdiv($item->MSN);
           $m->sub_div_name = Ogpdetail::subDivToName($m->sub_div_code);
           $m->meter_ping_date_time = str_replace('T', ' ', $item->PingDateTime);
        $m->save();
        }


    }
    return $this->redirect(['index']);
   }
}

Ниже приведены две функции

 public static function isVerified($msn)
{
    $meter = Installations::find()->where(['meter_msn'=>$msn])->one();

    if($meter)
        return true;
    return false;
}

public static function ogpCreated($msn,$date_time){
    $meter = Ogpdetail::find()->where(['meter_serial' => $msn])->one();

    if($meter)
    {
        if($date_time>$meter['created_at'])
            return true;
        return false;
    }
    else{
        return false;
    }

}

У меня есть консольный контроллер, в котором я пытаюсь вызвать выше action

namespace console\controllers;


use yii\console\Controller;
use Yii;

class CronController extends Controller {

public function actionIndex() {
    Yii::$app->controllerNamespace = "backend\controllers";

    Yii::$app->runAction('meterping/create');
}
}

Incmd Я использую следующую команду

E:\xampp\htdocs\inventory-web>php yii cron

Я получаю ошибку

Stack trace:
#0 E:\xampp\htdocs\inventory- 
web\backend\controllers\MeterpingController.php(126): 
backend\controllers\MeterpingController::isVerified('002999001152')
#1 [internal function]: backend\controllers\MeterpingController- 
>actionCreate()
#2 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\InlineAction.php(57): 
call_user_func_array(Array, Array)
#3 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Controller.php(156): yii\base\InlineAction- 
>runWithParams(Array)
#4 E:\xampp\htdocs\inventory-web\vendor\yiisoft\yii2\base\Module.php(523): 
yii\base\Controller->runAction('create', Array)
#5 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(180): yii\base\Module- 
>runAction('meterping/creat...', Array)
#6 E:\xampp\htdocs\inventory-web\console\controllers\CronController.php(24): 
yii\console\Application->runAction('meterping/creat...')
#7 [internal function]: console\controllers\CronController->actionIndex()
#8 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\InlineAction.php(57): 
call_user_func_array(Array, Array)
#9 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Controller.php(156): yii\base\InlineAction- 
>runWithParams(Array)
#10 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Controller.php(128): yii\base\Controller- 
>runAction('', Array)
#11 E:\xampp\htdocs\inventory-web\vendor\yiisoft\yii2\base\Module.php(523): 
yii\console\Controller->runAction('', Array)
#12 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(180): yii\base\Module- 
>runAction('cron', Array)
#13 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(147): 
yii\console\Application->runAction('cron', Array)
#14 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Application.php(380): yii\console\Application- 
>handleRequest(Object(yii\console\Request))
#15 E:\xampp\htdocs\inventory-web\yii(27): yii\base\Application->run()
#16 {main}

Ранее я звонил echo напрямую из actionIndex() и использовал ту же командуЯ смог увидеть правильный результат.Но вызов action с другого контроллера, похоже, не работает.

Примечание: Я хочу вызывать его по расписанию, поэтому я создал задание cron.

Как настроить мой код так, чтобы эта ошибка не отображалась в cmd?

Обновление 1

Согласно предложению и по этой ссылке

Я сделал следующее

  1. Создана папка components в папке common.
  2. Создан пользовательский компонент в папке компонентов

     namespace common\components;
    
    
     use Yii;
     use yii\base\Component;
     use yii\base\InvalidConfigException;
     use app\models\Installations;
     use app\models\Meters;
     use common\models\MeterPing;
     use common\models\MeterpingSearch;
     use common\models\Ogpdetail;
     use yii\web\Controller;
     use yii\web\NotFoundHttpException;
     use yii\filters\VerbFilter;
     use PhpOffice\PhpSpreadsheet\Spreadsheet;
     use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
     use PhpOffice\PhpSpreadsheet\Reader\Xls\Style;
     public function create() {
    
         //...My code   
    
     }
    
  3. Зарегистрирован компонент в common/config/main-local.php

     'components' => [
    
       'pingManager' => [
    
          'class' => 'common\components\MyComponent',
    
          ],
        ]
    
  4. В моем веб-контроллере я сделал следующее

    Yii::$app->pingManager->create();
    return $this->redirect(['index']);
    

Теперь, когда я пытаюсь получить к нему доступ через Интернет, выдается следующее сообщение об ошибке

Unable to find 'common\components\MyComponent' in file: E:\xampp\htdocs\inventory-web\common/components/MyComponent.php. Namespace missing?

Обновление 2

Мне не хватало имени класса, поэтому я обновил его до MyComponent и получил доступ к нему через Интернет.Это сработало.Теперь, когда я пытаюсь запустить его через консоль, я получаю ошибку ниже.

Exception 'Error' with message 'Class 'app\models\Installations' not found'

in E:\xampp\htdocs\inventory-web\common\components\MyComponent.php:89

Stack trace:
#0 E:\xampp\htdocs\inventory-web\common\components\MyComponent.php(65): 
common\components\MyComponent::isVerified('002999001064')
#1 E:\xampp\htdocs\inventory- 
web\backend\controllers\MeterpingController.php(148): 
common\components\MyComponent->create()
#2 [internal function]: backend\controllers\MeterpingController- 
>actionCreate()
#3 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\InlineAction.php(57): 
call_user_func_array(Array, Array)
#4 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Controller.php(156): yii\base\InlineAction- 
>runWithParams(Array)
#5 E:\xampp\htdocs\inventory-web\vendor\yiisoft\yii2\base\Module.php(523): 
yii\base\Controller->runAction('create', Array)
#6 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(180): yii\base\Module- 
>runAction('meterping/creat...', Array)
#7 E:\xampp\htdocs\inventory-web\console\controllers\CronController.php(24): 
yii\console\Application->runAction('meterping/creat...')
#8 [internal function]: console\controllers\CronController->actionIndex()
#9 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\InlineAction.php(57): 
call_user_func_array(Array, Array)
#10 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Controller.php(156): yii\base\InlineAction- 
>runWithParams(Array)
#11 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Controller.php(128): yii\base\Controller- 
>runAction('', Array)
#12 E:\xampp\htdocs\inventory-web\vendor\yiisoft\yii2\base\Module.php(523): 
yii\console\Controller->runAction('', Array)
#13 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(180): yii\base\Module- 
>runAction('cron', Array)
#14 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\console\Application.php(147): 
yii\console\Application->runAction('cron', Array)
#15 E:\xampp\htdocs\inventory- 
web\vendor\yiisoft\yii2\base\Application.php(380): yii\console\Application- 
>handleRequest(Object(yii\console\Request))
#16 E:\xampp\htdocs\inventory-web\yii(27): yii\base\Application->run()
#17 {main}

Число 89 равно $meter = Installations::find()->where(['meter_msn'=>$msn])->one();

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 01 июня 2018

Вероятно, это не тот ответ, который вы ожидали, но вам следует избегать этой проблемы в первую очередь.Если вам нужно вызывать код действия контроллера из другого места, у вас, вероятно, есть некоторые проблемы с дизайном в вашем приложении.Контроллеры должны быть тонкими и не содержать продвинутой логики или кода многократного использования.Если вам нужно вызвать действие контроллера из другого места, это действие, вероятно, слишком толстое, и вы должны извлечь его логику для разделения компонента или помощника.Итак, в вашем случае:

Создайте компонент и извлеките в него логику действий:

class PingManager extends \yii\base\Component {

    public function create($record, $start_time, $end_time, $data) {
        foreach ($record as $item) {
            $date_time = str_replace('T', ' ', $item->PingDateTime);
            if ($this->isSaved($item->MSN)) {
                // return true;
            } else {
                if ($this->isVerified($item->MSN)) {
                    // return true;
                } else {
                    if ($this->ogpCreated($item->MSN, $date_time)) {
                        $m = new MeterPing();
                        $m->load($data);
                        $m->start_date_time = str_replace('T', ' ', $start_time);
                        $m->end_date_time = str_replace('T', ' ', $end_time);

                        $m->meter_msn = $item->MSN;
                        $m->meter_id = Meters::msnmapToid($m->meter_msn);
                        $m->meter_type = Meters::mType($m->meter_msn);
                        $m->sub_div_code = Ogpdetail::msnTosubdiv($item->MSN);
                        $m->sub_div_name = Ogpdetail::subDivToName($m->sub_div_code);
                        $m->meter_ping_date_time = str_replace('T', ' ', $item->PingDateTime);
                        $m->save();
                    }
                }
            }
        }
    }

    private function isSaved($msn) {
        // todo
    }

    private function isVerified($msn) {
        $meter = Installations::find()->where(['meter_msn' => $msn])->one();
        if ($meter) {
            return true;
        }

        return false;
    }

    private function ogpCreated($msn, $date_time) {
        $meter = Ogpdetail::find()->where(['meter_serial' => $msn])->one();
        if ($meter) {
            return $date_time > $meter['created_at'];
        }

        return false;
    }
}

Зарегистрируйте компонент в конфигурации приложения:

'components' => [
    'pingManager' => [
        'class' => PingManager::class,
    ],
    // ...
],

Используйте его в контроллере консоли:

class CronController extends Controller {

    public function actionIndex() {
        // initialize $record, $start_time, $end_time, $data

        Yii::$app->pingManager->create($record, $start_time, $end_time, $data);
    }
}

А в веб-контроллере:

class MeterpingController extends Controller {

    public function beforeAction($action) {
        if ($action->id == 'create') {
            $this->enableCsrfValidation = false;
        }

        return parent::beforeAction($action);
    }

    public function actionCreate() {
        // initialize $record, $start_time, $end_time

        Yii::$app->pingManager->create($record, $start_time, $end_time, Yii::$app->request->post());
        return $this->redirect(['index']);
    }
}
...