Yii2 - Call a Yii console command from within anot

2020-07-08 07:18发布

问题:

I have created two different Yii2 console commands/controllers.

Example to call them is

# yii user/create-account

and

# yii webserver/update-config

After user/create-account has run I want to call webserver/update-config - is it possible doing this from within Yii by code? Or do I have to use exec()/system() to externally call the second yii php script (I would prefer not to).

Any help/insight would be appreciated!

回答1:

After some consideration the way I chose to call one controller from within another was by using the runAction method of the controller (which is also the recommended way by the Yii developers).

Example for a console application:

\Yii::$app->runAction('webserver/update-config');

It is also possible to hand over params by using an array in as second parameter.

An example for simple parameters:

\Yii::$app->runAction('webserver/update-config', ['oneValue', 'anotherValue'];

Here an example for named parameters:

\Yii::$app->runAction('webserver/update-config', [
    'servertype' => 'oneSetting', 
    'serverdir'  => 'anotherSettingValue'
]);

Please note that this makes the called controller a part of the calling code. So if the called controller fails for some reason the whole program fails. Good error handling is a must. In the called controller you can set the error code to give back by using return.

Example:

Calling line of code:

$iExitCode = \Yii::$app->runAction('webserver/update-config', ['oneValue', 'anotherValue'];

Called controller:

<?php
namespace app\commands;

use yii\console\Controller;

/**
* Webserver related functions
*/
class WebserverController extends Controller {
    public function actionUpdateConfig($oneValue, $anotherValue) {
        // Code that does something
        if ($success) return 0;
        else          return 1;
    }
}
?>


回答2:

Calling one action from another (even inside one controller) is not very good practice and clear. I suggest another approach.

Move updating webserver config logic outside of a Webserver controller, for example place it in some component / helper.

Then you can call this method from anywhere in particular in both user controller and webserver controller.

Example. In Webserver component:

public static function updateConfig()
{
    ...
}

In User controller:

public function actionCreateAccount()
{
    ...
    Webserver::updateConfig();
}

In Webserver controller:

public function actionUpdateConfig()
{
    Webserver::updateConfig();
}

I think this is more reusable and clear.



回答3:

Variant 1

You can run one action of controller from another action. For example,

public function actionCreateAccount() {
    // something
}

public function actionUpdateConfig() {
    // something
}

public function actionComplex() {
    $this->actionCreateAccount();
    $this->actionUpdateConfig();
}

Or

public function actionCreateAccount() {
    // something
    $this->actionUpdateConfig();
}

public function actionUpdateConfig() {
    // something
}

Variant 2

If you neet to call action of another controller, you can use run() method of console controller:

For example, action in WebmasterController:

public function actionUpdateConfig($param1, $param2)
{
    echo $param1 . '/' . $param2 . PHP_EOL;
}

action in UserController:

public function actionCreateAccount()
{
    echo 'test: ';
    $this->run('webmaster/update-config', ['do', 'it']);
}


标签: php shell yii2