Yii2: Console list command error while using undersore in action name

Created on 25 Jun 2019  路  19Comments  路  Source: yiisoft/yii2

What steps will reproduce the problem?

Any controller in console namespace with action name like

public function actionTest_01(){
// any code
}

So, using the underscore in the action name triggers the PHP Notice, without the underscore it is ok. Please note, that the underscores are officialy useable in the naming convention (https://subscription.packtpub.com/book/web_development/9781785287411/1/ch01lvl1sec12/naming-convention).

What is the expected result?

After using php yii or ./yii we should see the possible functions list under

"The following commands are available:"

What do you get instead?

The error appears, like so:

  • odbc-report Class OdbcReportController
    odbc-report/build-reporting-03PHP Notice 'yii\base\ErrorException' with message 'Trying to get property 'id' of non-object'

in /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Controller.php:601

Stack trace:

0 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Controller.php(601): yii\base\ErrorHandler->handleError(8, 'Trying to get p...', '/Applications/M...', 601, Array)

1 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Controller.php(456): yii\console\Controller->getActionMethodReflection(NULL)

2 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/controllers/HelpController.php(339): yii\console\Controller->getActionHelpSummary(NULL)

3 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/controllers/HelpController.php(67): yii\console\controllers\HelpController->getDefaultHelp()

4 [internal function]: yii\console\controllers\HelpController->actionIndex(NULL)

5 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)

6 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction->runWithParams(Array)

7 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Controller.php(148): yii\base\Controller->runAction('', Array)

8 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/base/Module.php(528): yii\console\Controller->runAction('', Array)

9 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Application.php(180): yii\base\Module->runAction('', Array)

10 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/console/Application.php(147): yii\console\Application->runAction('', Array)

11 /Applications/MAMP/htdocs/site/vendor/yiisoft/yii2/base/Application.php(386): yii\console\Application->handleRequest(Object(yii\console\Request))

12 /Applications/MAMP/htdocs/site/yii(27): yii\base\Application->run()

13 {main}

Additional info

| Q | A
| ---------------- | ---
| Yii version | 2.0.18
| PHP version | 7.2.14
| Operating system | MacOS, Linux

bug

All 19 comments

I can confirm,
In HelpController#291 the list of actions in a controller is fetched here HelpController#329

Names of public actions of the controller go through the Inflector::camel2id method so actionTest_01 becomes test-01, underscore changed to a dash.
It's then trying to create an action using the new name which doesn't exist HelpController#339

Currently, it converts actionTest_01 to test/test-01 command name, is it correct? Or it should be test/test_01?
Another example actionTest_test -> test/test-test, should it be test/test_test?

I think it is now consistent with what is done in web application controller.

Another note is this only affects actions within the controller itself.
If it's in the actions method it'll work, e.g.

public function actions()
{
  return [
    'my_action' => '...'
  ];
}

@samdark, so, the current behavior is correct? In this case, two different actions will have the case command name actionTestTest and actionTest_test -> test-test

'Trying to get property 'id' of non-object' is definitely incorrect.

I understand that should be no error, but I'm trying to understand what should be fixed, either converting action method name to command name or command name to method name. As there are two places where it can be fixed.
But if we leave this logic actionTest_test -> test/test-test we can't find correct method by command name as it's trying to find actionTestTest.

I think the conversion logic is OK and it could be fixed with checking both variants.

What if there are both methods (actionTest_test and actionTestTest) exist in the controller, which one should be used? Which is unlikely but still can be the case.

Let it be actionTestTest.

it could be fixed with checking both variants

@samdark, not only two variants are possible because there could be more complex action names, like actionTestTest_test_test it will generate the following command name test-test-test-test and in order to find correct action name we need to check lots of cases as we don't know which dash in the command name corresponds to the replaced underscore. So, we need a bit more complex logic to match the action name (see PR).

I think the conversion logic is OK and it could be fixed with checking both variants.

Big :-1: from me - it creates unnecessary ambiguous and complicates implementation. What is the benefit of treating _ in this way?

@rob006 how would you solve it?

Leave _ untouched, so actionTest_test -> test_test.

Won't that break backwards compatibility?

AFAIK actions with _ never worked, so how it could break BC?

Just to note,

class ConsoleController extends \yii\console\Controller
{
    public function actions()
    {
        return [
            'test_test' => \app\actions\Action::class,
            'test-test' => \app\actions\Action::class,
        ];
    }
}
./yii
- console
  console/test_test
  console/test-test

@alex-code, in this case, there is no conversion between the action method name and the console command name.

@alexkart, is it hard to adjust behavior as @rob006 suggested?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MUTOgen picture MUTOgen  路  3Comments

sobit picture sobit  路  3Comments

kminooie picture kminooie  路  3Comments

psfpro picture psfpro  路  3Comments

indicalabs picture indicalabs  路  3Comments