bug #31493 [EventDispatcher] Removed "callable" type hint from WrappedListener constructor (wskorodecki)

This PR was merged into the 4.3 branch.

Discussion
----------

[EventDispatcher] Removed "callable" type hint from WrappedListener constructor

| Q             | A
| ------------- | ---
| Branch?       | 4.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| License       | MIT

### The problem

```php
public function __construct(callable $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
```

The *callable* type hint will cause the following exception if you register a listener class with a method, which could not be auto-guessed by the Symfony:

`Argument 1 passed to Symfony\Component\EventDispatcher\Debug\WrappedListener::__construct() must be callable, array given`

The debug toolbar will not be displayed in this case.

This is because PHP is checking the array first before making a decision if this is a valid callable or not. So if the second array element does not represent an existing method in object from the first element - PHP will treat this as a common array, not callable. Use `is_callable` method if you need a proof.

### How to reproduce

1. Register some listener with a method, which could not be auto-guessed by Symfony
2. Do not create the `__invoke` method in the listener
3. Skip the `method` attribute in the listener configuration

Example:

```php
class SomeListener
{
    public function myListenerMethod(SomeEvent $event)
    {
        // ...
    }
}
```

```yaml
App\EventListener\SomeListener:
    tags:
      -
        name: kernel.event_listener

        # Symfony will look for "onSomeEvent" method which does not exists.
        event: 'some.event'
        #method: 'myListenerMethod' # Skip this.
```

### Solution:

Removing the type hint will cause the \Closure::fromCallable() method to throw a proper exception, for example:

`Symfony\Component\Debug\Exception\FatalThrowableError(code: 0): Failed to create closure from callable: class 'App\EventListener\SomeListener' does not have a method 'onSomeEvent'`

Commits
-------

20c587fc23 [EventDispatcher] Removed "callable" type hint from WrappedListener constructor
This commit is contained in:
Fabien Potencier 2019-05-18 18:11:27 +02:00
commit e606ac1916
1 changed files with 1 additions and 1 deletions

View File

@ -38,7 +38,7 @@ class WrappedListener
private $priority;
private static $hasClassStub;
public function __construct(callable $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
{
$this->listener = $listener;
$this->optimizedListener = $listener instanceof \Closure ? $listener : \Closure::fromCallable($listener);