Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[HttpKernel] Better exception page when the controller returns nothing#27138
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
69dd0c0 to31a63b9Compare| throw$e; | ||
| } | ||
| $r =new \ReflectionProperty(\Exception::class,'trace'); |
nicolas-grekasMay 3, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
What about using a rebound closure instead of reflection? It'd make things easier to read IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Warning: Cannot bind closure to scope of internal class Exception
| $r->setAccessible(true); | ||
| $r->setValue($e,array_merge(array( | ||
| array( | ||
| 'line' =>$e->getLine(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This could be even more accurate, passing the line of the call_user_fun above (using__LINE__ next to it.)
Aren't they other keys we should put in the frame? How does it look when thrown from inside the controller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
fixed
| } | ||
| if (is_object($controller)) { | ||
| $r =new \ReflectionClass($controller); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
method__invoke()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
yes
BTW, I adapted the code from
symfony/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php
Lines 373 to 425 in667924c
| protectedfunctionparseController($controller) | |
| { | |
| if (is_string($controller) &&false !==strpos($controller,'::')) { | |
| $controller =explode('::',$controller); | |
| } | |
| if (is_array($controller)) { | |
| try { | |
| $r =new \ReflectionMethod($controller[0],$controller[1]); | |
| returnarray( | |
| 'class' =>is_object($controller[0]) ?get_class($controller[0]) :$controller[0], | |
| 'method' =>$controller[1], | |
| 'file' =>$r->getFileName(), | |
| 'line' =>$r->getStartLine(), | |
| ); | |
| }catch (\ReflectionException$e) { | |
| if (is_callable($controller)) { | |
| // using __call or __callStatic | |
| returnarray( | |
| 'class' =>is_object($controller[0]) ?get_class($controller[0]) :$controller[0], | |
| 'method' =>$controller[1], | |
| 'file' =>'n/a', | |
| 'line' =>'n/a', | |
| ); | |
| } | |
| } | |
| } | |
| if ($controllerinstanceof \Closure) { | |
| $r =new \ReflectionFunction($controller); | |
| returnarray( | |
| 'class' =>$r->getName(), | |
| 'method' =>null, | |
| 'file' =>$r->getFileName(), | |
| 'line' =>$r->getStartLine(), | |
| ); | |
| } | |
| if (is_object($controller)) { | |
| $r =new \ReflectionClass($controller); | |
| returnarray( | |
| 'class' =>$r->getName(), | |
| 'method' =>null, | |
| 'file' =>$r->getFileName(), | |
| 'line' =>$r->getStartLine(), | |
| ); | |
| } | |
| returnis_string($controller) ?$controller :'n/a'; | |
| } |
31a63b9 to93ecc0bCompare| // call controller | ||
| $response =\call_user_func_array($controller,$arguments); | ||
| $response =\call_user_func_array($controller,$arguments);$line =__LINE__; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would put this on the next line using$line = __LINE__ - 1; instead. The current code does not comply with our coding standards, and would force to exclude the whole HttpKernel.php file from the CS tooling to avoid having PHP-CS-Fixer breaking it on each run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
done
93ecc0b to36dacd7Compare| 'line' =>$r->getStartLine(), | ||
| ); | ||
| }catch (\ReflectionException$e) { | ||
| returnnull; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
trynew \ReflectionClass($controller[0])?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
To get only the file?
nicolas-grekasMay 3, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yes, WDYT ? And start line of the class of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Why not, But I don't know how to "simulate" this fail :/ Do you know how to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Looking at RequestDataCollector I'd say using__call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I don't understand. Sorry.
If the method does not exist in the first place Symfony throw an error.
I don't want to add dead code to Symfony, so please give me a reproducer ;)
nicolas-grekas commentedMay 3, 2018
WDYT of moving all the added logic to a new exception class, child of LogicException? |
8c5d7b2 toc8f75e5Comparelyrixx commentedMay 4, 2018 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@nicolas-grekas I added the new Exception class. Note: Exception::trace is private, So I need reflection. line and file are protected ;). |
| } | ||
| thrownew \LogicException($msg); | ||
| thrownewControllerDoesNotReturnResponseException($msg,$controller,__FILE__,__LINE__ -17); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
we need a test case to ensure we won't miss updating this "17" in the future I suppose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Tests added
c8f75e5 tof1e9aa4Comparefabpot commentedMay 9, 2018
Thank you@lyrixx. |
… returns nothing (lyrixx)This PR was merged into the 4.2-dev branch.Discussion----------[HttpKernel] Better exception page when the controller returns nothing| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets |#27137| License | MIT| Doc PR |---Before:after:Commits-------f1e9aa4 [HttpKernel] Better exception page when the controller returns nothing
…controller returns nothing (dimabory)This PR was merged into the 4.3-dev branch.Discussion----------[HttpKernel] Better exception page when the invokable controller returns nothing| Q | A| ------------- | ---| Branch? | master| Bug fix? | no| New feature? | yes| BC breaks? | no| Deprecations? | no| Tests pass? | yes| Fixed tickets |#27138| License | MIT| Doc PR |---__Prerequisites___Configure invokable controller_```php# config/routes.yamlindex: path: / controller: App\Controller\Start```__Before:____After:__---Take a look for an enhancement/refactoring in `HttpKernel.php`Commits-------f6c1622 [HttpKernel] Better exception page when the invokable controller returns nothing
Uh oh!
There was an error while loading.Please reload this page.
Before:
after: