Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2 - Call a Yii console command from within another console command?

Tags:

shell

php

yii2

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!

like image 523
Deckard Avatar asked Oct 29 '15 16:10

Deckard


2 Answers

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;
    }
}
?>
like image 105
Deckard Avatar answered Oct 23 '22 09:10

Deckard


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.

like image 30
arogachev Avatar answered Oct 23 '22 09:10

arogachev