Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command::execute() should always return int - deprecate returning null #33747

Closed
nicolas-grekas opened this issue Sep 28, 2019 · 20 comments · Fixed by #33775
Closed

Command::execute() should always return int - deprecate returning null #33747

nicolas-grekas opened this issue Sep 28, 2019 · 20 comments · Fixed by #33775
Labels
Console Deprecation Help wanted Issues and PRs which are looking for volunteers to complete them.
Projects

Comments

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Sep 28, 2019

Right now, Command::execute() returns int|void.

I'd suggest we should deprecate returning void (or null) by throwing a deprecation when the method returns a non-int, in Application.

We would need to update all core commands to return 0; where they return; right now.

And in 5.0, we would make returning a non-int throw an exception, in preparation for adding a real return type in 6.0.

Help wanted.

@nicolas-grekas nicolas-grekas added the Help wanted Issues and PRs which are looking for volunteers to complete them. label Sep 28, 2019
@nicolas-grekas nicolas-grekas added this to Nicolas' in Help Wanted Sep 28, 2019
@nicolas-grekas nicolas-grekas changed the title Command::execute() should always return int - deprecete returning null Command::execute() should always return int - deprecate returning null Sep 30, 2019
@ihmels
Copy link
Contributor

ihmels commented Sep 30, 2019

I think that's a good idea. Why not add a return type in 5.0 so that a TypeError would be thrown? 🤔

@jschaedl
Copy link
Contributor

jschaedl commented Sep 30, 2019

So we basically need to do the following:

Tasks in 4.4

First of all we need to introduce a deprecation message for nullable or non-int return values of Command::execute()

After that we can adjust the core commands with exchanging return; to return 0; and add a return type-hint for the overridden method protected function execute(InputInterface $input, OutputInterface $output), but only for Command classes which are declared final (@nicolas-grekas Can we include Commands annotated with@final as well?):

I checked all Bundles and Bridges which provide Commands:

Tasks in 5.0

@nicolas-grekas
Copy link
Member Author

@ihmels see #33236 for background on the topic

@jschaedl your list looks good

Can we include Commands annotated with @final as well?

yes, unless the annotation says @final since ..., which means "not before 5.0"

xabbuh added a commit that referenced this issue Oct 2, 2019
…DebugCommand (jschaedl)

This PR was merged into the 3.4 branch.

Discussion
----------

[FrameworkBundle] Fix wrong returned status code in ConfigDebugCommand

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix #33747<!-- prefix each issue number with "Fix #", if any -->
| License       | MIT
| Doc PR        | -

This is a follow-up PR caused by #33775 (comment)

Commits
-------

9b5ced2 [FrameworkBundle] Fix wrong returned status code in ConfigDebugCommand
nicolas-grekas added a commit that referenced this issue Oct 2, 2019
…de (jschaedl)

This PR was merged into the 4.4 branch.

Discussion
----------

[Console] Add deprecation message for non-int statusCode

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | yes <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix #33747 <!-- prefix each issue number with "Fix #", if any -->
| License       | MIT
| Doc PR        | -

### What was done:

- [x] added deprecation message for non-int return value in Command::execute()
- [x] fixed all core commands to return proper int values
- [x] added proper return type-hint to Command::execute() method in all core Commands

Commits
-------

98c4f6a [Console] Command::execute() should always return int - deprecate returning null
nicolas-grekas added a commit that referenced this issue Oct 2, 2019
…ling Command::execute() (jschaedl)

This PR was merged into the 5.0-dev branch.

Discussion
----------

[Console] Throw a TypeError for non-int return value calling Command::execute()

| Q             | A
| ------------- | ---
| Branch?       | 5.0
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | yes <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix #33747 <!-- prefix each issue number with "Fix #", if any -->
| License       | MIT
| Doc PR        | - <!-- required for new features -->

### Todo

- [x] needs to be rebased after 4.4 was merged into master (see: #33805)

Commits
-------

b3a3b0c [Console] Throw a TypeError for non-int return values on calling Command::execute()
SpacePossum added a commit to PHP-CS-Fixer/PHP-CS-Fixer that referenced this issue Oct 8, 2019
…bus)

This PR was merged into the 2.15 branch.

Discussion
----------

Command::execute() should always return an integer

In Symfony 4.4, a deprecation error is triggered if `Command::execute()` does not return an integer, see symfony/symfony#33747. This PR adds the necessary `return` statements.

Commits
-------

ee758b1 Command::execute() should always return an integer.
@andig
Copy link

andig commented Dec 3, 2019

I realize its too late but the PR doesn't give any reasoning as to why this change is helpful. It does break a large number of projects (or anyway it broke all of mine) and it makes the code fairly ugly with the lone return 0 at the end of any execute() method. Personally, I find this totally counterproductive.

mikeyclarke added a commit to mikeyclarke/Hipper that referenced this issue Dec 8, 2019
Per symfony/symfony#33747, required for
Symfony 5.0 upgrade.
@halaei
Copy link

halaei commented Dec 15, 2019

I don't get this restriction. Even in a strictly typed language like C I can have an int function that returns nothing, it will be automatically converted to 0. Also you can define main as being void. So why C is more flexible than Symfony here?

@vekien
Copy link

vekien commented Mar 10, 2020

According to: https://symfony.com/doc/current/contributing/community/releases.html

A new Symfony minor version (e.g. 2.8, 3.2, 4.1) comes out every six months: one in May and one in November. It contains bug fixes and new features, but it doesn't include any breaking change, so you can safely upgrade your applications;

But 4.4 this is now throwing an exception, and broke all of my commands? Why is this forced in 4.4 and not 5.0? This is the second thing now that Symfony have broke stuff in a minor version.....

@xabbuh
Copy link
Member

xabbuh commented Mar 10, 2020

Can you be a bit more precise how this broke your application?

@andig
Copy link

andig commented Mar 11, 2020

Can you be a bit more precise how this broke your application?

It changes the execute method's signature and that constitutes a breaking change.

I realize its too late but the PR doesn't give any reasoning as to why this change is helpful.

It will throw a notice AND break phpstan.

We would need to update all core commands to return 0; where they return; right now.

You're forcing this on every developer using symfony commands. I feel the question alone shows little empathy for the developers hit by this change.

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

It changes the execute method's signature and that constitutes a breaking change.

The method signature of the Command class was changed in 5.0 where we intentionally did BC breaks. But that doesn't break applications updating from 4.3 to 4.4.

@vekien
Copy link

vekien commented Mar 11, 2020

So you can see in 4.4 the trigger_error is set here: https://github.com/symfony/console/blob/4.4/Command/Command.php#L258 while it does have a @ it wont stop it being thrown in CLI scripts.

So many of my scripts (near 100 of them) all started throwing "Return value of X::execute() should always be of type int since Symfony 4.4".

The only fix was for me to go in and update all of them, thankfully it's quite an easy fix since I can just shove return 0 on them all, but this is still a BC as the command would still stop when this was thrown. (Could it be due to try/catches? many run in Queues and need this)

Example

image

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

This looks like an issue with your setup if silenced deprecations are turned into errors.

@andig
Copy link

andig commented Mar 11, 2020

This looks like an issue with your setup if silenced deprecations are turned into errors.

If feel strongly that my setup should not be dictatored by libraries used.

See my comment about phpstan. It does also break the CI build process due to https://github.com/symfony/console/blob/4.4/Command/Command.php#L153.

That being said, the PR also does not provide any reason for doing so in 4.4.

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

Symfony is using this way to trigger deprecations since at least 2.8. If your error handler doesn't respect the silenced errors that is indeed something we cannot fix in the core.

That being said, the PR also does not provide any reason for doing so in 4.4.

We always deprecate things in a minor release (4.4 here) before removing it in the next major version (5.0 here) to provide a smooth upgrade path.

@dbrumann
Copy link
Contributor

This looks like an issue with your setup if silenced deprecations are turned into errors.

If feel strongly that my setup should not be dictatored by libraries used.

By default @ will silence errors. See: https://www.php.net/manual/en/language.operators.errorcontrol.php

If you have set a custom error handler function with set_error_handler() then it will still get called, but this custom error handler can (and should) call error_reporting() which will return 0 when the call that triggered the error was preceded by an @.

It seems that your error handler decides to ignore the intention behind the operator. Symfony does not "dictate" how you do things, but if you change rightfully expected behavior, you are responsible for the consequences.

@vekien
Copy link

vekien commented Mar 11, 2020

So because I have a try/catch it becomes BC??? That is extremely janky, libraries should expect people to have error handling...

I have no custom error handling other than a try/catch, the rest is pure symfony, an example can be followed here: https://github.com/xivapi/xivapi.com/blob/master/src/Command/GameData/SaintCoinachRedisCommand.php

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

Your error handler defined on line 75 of that exact class does not respect silenced errors.

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

You may want to update it like this:

set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
    if (0 === error_reporting()) {
         return;
    }
    # print_r($errcontext);
    throw new \Exception("{$errfile} {$errline} - {$errstr}", 0);
});

@vekien
Copy link

vekien commented Mar 11, 2020

Thanks @xabbuh i had wrongly assumed because it forced throwing exceptions which were catch later on it would be fine, reading your post I see it removes the silence, so this is my mistake, really sorry

@xabbuh
Copy link
Member

xabbuh commented Mar 11, 2020

I am glad we were able to resolve your issue. :)

@fmonts
Copy link

fmonts commented Sep 2, 2020

I think a : int should be added here so the IDE will warn you if you override it with :void? I stayed with 4.4 for about a year and never noticed the deprecation, only now that I upgraded to 5.1 I saw the error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Console Deprecation Help wanted Issues and PRs which are looking for volunteers to complete them.
Projects
Help Wanted
Nicolas'
Development

Successfully merging a pull request may close this issue.

10 participants