-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Handle case of static controller method and controllers using magic __call() method #6080
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
Conversation
$this->data['controller'] = array( | ||
'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], | ||
'method' => $controller[1], | ||
'file' => 'n/a/', |
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.
there is a trailing /
that should be removed.
Can you add some unit tests? |
'line' => $r->getStartLine(), | ||
); | ||
} catch (\ReflectionException $re) { | ||
if (is_callable($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.
Here the function is_callable
will only work if $controller[0]
is an object.
So either the line
'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0]
can be changed to
'class' => get_class($controller[0])
or this line should be changed to
if(is_callable($controller) || method_exists($controller[0], '__call'))
After the if you can also add the folling
$r = new \ReflectionClass($controller[0]);
Then you can add the file name
'file' => $r->getFilename(),
instead of n/a and for the line you can add
'line' => $r->getMethod('__call')->getStartLine()
* Drop surplus '/' in RequestDataCollector.php * Add unit test for the various callable forms
@pierredup The test I added also shows that the code works as is :) I've thought about your suggestion of adding reflection to look up the location of __call(). However, I think this doesn't really add a lot and only complicates matters. Also, as you can see in the new test, there is also __callStatic() to consider. The fact that file/line are n/a is correct, because the most typical case will be that __call() and __callStatic() will delegate to some other method that might not even be in the same class/file (a subclass I would expect), IMHO. @fabpot |
True that Take the following example:
Here Of course if you have a Your tests doesn't seem to cover this use case |
Hmm, maybe. I have to admin that I do not know about this case. OTOH, if is_callable returns false is it really callable then? I would think this more of a PHP bug then? I think I might have come across this case during coding, but then dismissed it because in that case FilterControllerEvent failed already before the data collector code is reached. In FilterControllerEvent there is a check on is_callable and a LogicException is thrown if $controller is not callable. So, is FilterControllerEvent wrong too then? |
One would think that if is_callable returns false, then the controller isn't callable, but in the case I mentioned above, the controller is in fact callable. I also thought it was a bug with php, but the php-internals don't seem to think so. The problem is, if you specify the class as a string, php looks for a static method, even if you have a __call method, it won't be registered. I will have a look at the FilterControllerEvent to see if this use case applies there as well. |
Rather strange - if that is the case then using is_callable seems pretty pointless and the only way would be to try to execute the controller to find out if it is, in fact, callable... |
Okay so it actually seems that the case above isn't callable after all. If the controller is specified as a string, then a static method need to exist. Hence why it works with __callStatic. Only when an instance of the class is specified, will it handle the __call method. |
So the tests are sufficient then? |
Yes it is. Sorry for the hassle |
Improve collecting controller details for edge cases where: