JahangirAhmad
JahangirAhmad

Reputation: 174

How to call a console command in web application action in Yii?

I have a console command to do a consumer time, AND I need to know how to call (execute) it in a web application action in YII.

class MyCommand extends CConsoleCommand{
      public function actionIndex(){
          $model = new Product();
          $model->title = 'my product';
          ...
          $model->save();
          .
          .
          .
      }
}

I want to execute this code.

Upvotes: 7

Views: 24872

Answers (7)

Sebastian Viereck
Sebastian Viereck

Reputation: 5887

try this:

    Yii::import('application.commands.*');
    $command = new MyCommand("test", "test");
    $command->run(null);

The 2 parameters with value "test" must be set but do not have an impact, they are used for the --help option when using the console.

/**
 * Constructor.
 * @param string $name name of the command
 * @param CConsoleCommandRunner $runner the command runner
 */
public function __construct($name,$runner)
{
    $this->_name=$name;
    $this->_runner=$runner;
    $this->attachBehaviors($this->behaviors());
}

https://github.com/yiisoft/yii/blob/master/framework/console/CConsoleCommand.php#L65

Upvotes: 36

user4204642
user4204642

Reputation:

Accepting that we are on linux server, for Yii 1.1 real life example would be:

$run = '/usr/bin/php ' . Yii::getPathOfAlias('root').'/yiic' [command]
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $run, '/dev/null', '/dev/null'));

This will run Yii console command in the background.

Upvotes: 1

David Newcomb
David Newcomb

Reputation: 10943

Typically what you should do in these situations is refactor. Move the "common" code out of the MyCommand and place it into a class located in the components folder. Now you can place any head on top of the "common" code without altering your functionality. For example:

protected/components/Mywork.php:

<?php
class Mywork
{
    public function doWork()
    {
        $model = new Product();
        $model->title = 'my product';
        ...
        $model->save();
        ...
    }
}

protected/controller/MyworkController.php:

<?php
class MyworkController
{
    public function actionDowork()
    {
        $mywork = new Mywork;
        ...
    }
}

protected/commands/MyworkCommand.php:

<?php
class MyworkCommand extends CConsoleCommand
{
    public function run($args)
    {
        $mywork = new Mywork;
        ...
    }
}

This approach makes testing easier too as you can test Mywork as a single unit outside of the view you are using.

Upvotes: 0

ggirtsou
ggirtsou

Reputation: 2048

Also, another very clean solution from cebe on gist:

<?php
// ...
$runner=new CConsoleCommandRunner();
$runner->commands=array(
    'commandName' => array(
        'class' => 'application.commands.myCommand',
    ),
);

ob_start();
$runner->run(array(
    'yiic',
    'idbrights',
));
echo nl2br(htmlentities(ob_get_clean(), null, Yii::app()->charset));

Yii::app()->end();

Upvotes: 1

Filsh
Filsh

Reputation: 1118

Try this

Yii::import('application.commands.*');
$command = new GearmanCommand('start', Yii::app()->commandRunner);
$command->run(array('start', '--daemonize', '--initd'));

where array('start', '--daemonize', '--initd') is a action and action parameters

Upvotes: 5

llamerr
llamerr

Reputation: 3186

I had same problem - i need to call action from inside controller and from command

I said same problem because it actually same - you have action which you need to call from console, and call it from controller too.

If you need to call an action(command) as a part of controller action, then i think you need to modify this solution a little. Or is my solution is enough for you?

So here is my solution:

first create action as said in http://www.yiichina.net/doc/guide/1.1/en/basics.controller#action

class NotifyUnsharedItemsAction extends CAction
{
    public function run()
    {
        echo "ok";
    }
}

then in controller action is loaded as usuall:

class TestController extends Controller
{

    public function actions() {
        return array(
            'notifyUnsharedItems'=>'application.controllers.actions.NotifyUnsharedItemsAction',
    );
}

and in command i run action in such way:

class NotifyUnsharedItemsCommand extends CConsoleCommand
{
    public function run($args)
    {
        $action = Yii::createComponent('application.controllers.actions.NotifyUnsharedItemsAction',$this,'notify');
        $action->run();
    }

}

Upvotes: 2

KillerX
KillerX

Reputation: 1466

Yii is PHP -> you can use the standard php constructs specified at http://php.net/manual/en/function.exec.php and the related methods near the bottom of the page, depending on what exactly you want to achieve.

Upvotes: 1

Related Questions