We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

CLI: Argument passed to Action as array

We just upgraded our application to PHP7 with Phalcon 3.0.3. Before this upgrade, we were working with PHP 5.6 and Phalcon 2.0.13.

Without event touching anything, we discovered that one of our Tasks is not working anymore.

To access our CLI module, we perform this call:

php cron.php name_of_task name_of_action arg1 arg2

In order to deduce the name of the Task and the name of the Action to call from the arguments passed, we implemented this method in cron.php:

private function parseArguments() {
    global $argv, $argc;

    $parameters = array();

    $dispatcher = $this->getDI()->get('dispatcher');

    if( isset( $argv ) and ( $argc > 0 ) ) {
        foreach( $argv as $k => $arg ) {
            if( $k == 1 ) {
                $dispatcher->setTaskName( $arg );

            } elseif( $k == 2 ) {
                $dispatcher->setActionName( $arg );

            } elseif( $k >= 3 ) {
                $parameters[] = $arg;
            }
        }
    }

    $dispatcher->setParams( $parameters );
}

Everything works fine (just like before the upgrade) excepts for those Actions that require one or more arguments.

For example, if we call:

php cron.php test test 1

The Dispatcher instantiates TestTask and invokes testAction( $argument ).

However, if the first instruction of TestTask::testAction() is:

var_dump( $argument );
exit;

The printed result is:

array(1) {
    [0]=>
        string(1) "1"
}

instead of just:

string(1) "1"

Why?

    if( isset( $argv ) and ( $argc > 0 ) ) {
        foreach( $argv as $k => $arg ) {
            if( $k == 1 ) {
                $dispatcher->setTaskName( $arg );

            } elseif( $k == 2 ) {
                $dispatcher->setActionName( $arg );

            } elseif( $k >= 3 ) {
                $parameters[] = $arg;                                 <---------- this is why it is an array
            }
        }
    }

    $dispatcher->setParams( $parameters );


12.9k
   if( isset( $argv ) and ( $argc > 0 ) ) {
       foreach( $argv as $k => $arg ) {
           if( $k == 1 ) {
               $dispatcher->setTaskName( $arg );

           } elseif( $k == 2 ) {
               $dispatcher->setActionName( $arg );

           } elseif( $k >= 3 ) {
               $parameters[] = $arg;                                 <---------- this is why it is an array
           }
       }
   }

   $dispatcher->setParams( $parameters );

Are you sure?

  • Before upgrading to PHP7/Phalcon 3 that line was not a problem at all
  • If you're right, how can I pass 2, 3, or more arguments to an Action?
  • The dispatcher calls call_user_func_array(), which accepts an array containing the arguments for the function/method (1 or more): did PHP7 changed the way call_user_func_array() works?

Something fishy is afoot, because in Phalcon 2.0.x we reparse the argument array, create a custom object from it, and pass that in to all actions. This all happens before passing it to Console::handle().

In Phalcon 3.x that approach doesn't work at all.



12.9k

Something fishy is afoot, because in Phalcon 2.0.x we reparse the argument array, create a custom object from it, and pass that in to all actions. This all happens before passing it to Console::handle().

In Phalcon 3.x that approach doesn't work at all.

Ok, so what can I do now?



12.9k

If the Action accepts 2 parameters, only the first argument is defined and it is the same array passed to call_user_func_array() so:

php cron.php test test 123 5

with testAction accepting two parameters: public function testAction( $one, $two = true ):

  • var_dump( $one ):
array(2) {
  [0]=>
  string(3) "123"
  [1]=>
  string(1) "1"
}
  • var_dump( $two ):
bool(true)

With no default value for $two, it throws an error:

 Missing argument 2 for Namespace\Name\ClassTask::testAction()

We didn't have time to debug it, so we stayed on 2.0.x...

By default, the handle() will pass in only ONE array as an argument: https://docs.phalcon.io/en/latest/reference/cli.html#processing-action-parameters

I'm guessing you created your own logic somewhere to pass them in as a list, not just one variable, and the changes in Phalcon 3 messed that up (that's kind of what happened with us)



12.9k

We didn't have time to debug it, so we stayed on 2.0.x...

By default, the handle() will pass in only ONE array as an argument: https://docs.phalcon.io/en/latest/reference/cli.html#processing-action-parameters

I'm guessing you created your own logic somewhere to pass them in as a list, not just one variable, and the changes in Phalcon 3 messed that up (that's kind of what happened with us)

Ok, thanks. I didn't notice that page of the docs. Apparently they actually CHANGED the way the arguments are passed to Actions.

I just can't understand WHY... ?!?!