1

The Error

Hello, I am getting the following error:

Type error: Argument 2 passed to ApiExceptionBundle\EventListener\ApiExceptionSubscriber::__construct() must implement interface ApiExceptionBundle\Component\Factory\ResponseFactoryInterface, string given, called in C:\htdocs\projects\myproject\var\cache\dev\appDevDebugProjectContainer.php on line 4293

The Call Stack Showing The Incorrect Parameter Type Being Passed

As can be seen below from the call stack, the second parameter is a string. (But it should actually be an object instantiated of that type).

at ApiExceptionSubscriber->__construct(true, 'ApiExceptionBundle\\Component\\Factory\\ResponseFactoryInterface', true, array('/admin/'))
in appDevDebugProjectContainer.php (line 4293)

The Constructor Definition

The subscriber is located at myproject\src\ApiExceptionBundle\EventListener\ApiExceptionSubscriber.php and its constructor definition is the following:

public function __construct($debug, ResponseFactoryInterface $responseFactory, $enabled = true, $excludedPaths = [])

(Notice above that it is expecting a ResponseFactoryInterface object rather than a string).

The Services.yml Entry

In myproject/src/ApiExceptionBundle/Resources/config/services.yml, the relevant entry is below:

ApiExceptionBundle\EventListener\ApiExceptionSubscriber:
        arguments:
            $responseFactory: 'ApiExceptionBundle\Component\Factory\ResponseFactoryInterface'

Other Things I've Tried

From the original example I am using, I see that there is actually an @ symbol at the beginning of the $responseFactory argument assignment in the services.yml file.

The original code that I am using as an example, has a services.yml entry similar to this:

$responseFactory: '@ApiExceptionBundle\Component\Factory\ResponseFactoryInterface'

Unfortunately when I try to add the @ symbol in my code (like above), it gives me this error:

PHP Fatal error:  Uncaught Symfony\Component\DependencyInjection\Exception\RuntimeException: Cannot dump de
finition because of invalid class name ('@ApiExceptionBundle\\Component\\Factory\\ResponseFactory') in C:\h
tdocs\projects\myproject\vendor\symfony\symfony\src\Symfony\Component\DependencyInjection\Dumper\PhpDumper.ph
p:1568

Questions

So, I have 2 questions:

  1. What am I doing wrong? (I'm assuming it's the way I'm referencing things in services.yml).
  2. What does the @ symbol do? Taking a guess, I think it tells the code to instantiate an object of the class referenced rather than just literally using the string. Is that correct?
khgm13
  • 63
  • 7
  • 1
    You do need the @ sign to inject a service instead of a string. Are you sure that ApiExceptionBundle\Component\... is correct? I suspect it is actually ApiExceptionBundle\Factory\ResponseFactory. Need to change the constructor as well. Your IDE should tell you if you have the correct class name. And if dropping the Component portion is actually the solution then you probably don't need a services.yml entry at all. – Cerad Feb 02 '18 at 00:43
  • And you will also need to set $debug in the services.yml file as well. – Cerad Feb 02 '18 at 00:52
  • 1
    Thank you for your response and for explaining what the @ symbol means Cerad. I ended up using the suggestion that Tomáš posted below and it ended up working. I kept the "Component" part in as that was how the path was structured. As for the $debug entry, I already had that in services.yml (i.e. $debug: '%kernel.debug%' in the arguments section) but had taken it out of my question in order to simplify things a bit. – khgm13 Feb 02 '18 at 20:36

1 Answers1

0

For Symfony 3.3+

Looks like you're trying to pass interfaces. Specific instance should be used instead.

Have you tried autowiring with alias?

# services.yml

services:
    ApiExceptionBundle\YourResponseFactory: ~
    ApiExceptionBundle\Component\Factory\ResponseFactoryInterface:
        alias: ApiExceptionBundle\YourResponseFactory

    ApiExceptionBundle\EventListener\ApiExceptionSubscriber:
        autowire: true

With PSR-4 autodiscovery

Or you can use PSR-4 autodiscovery:

# services.yml

services:
    _defaults:
        autowire: true

    ApiExceptionBundle\: ~
        resource: ../ # path to ApiExceptionBundle directory

    ApiExceptionBundle\Component\Factory\ResponseFactoryInterface:
        alias: ApiExceptionBundle\YourResponseFactory

Symfony 3.4+

Since Symfony 3.4 you can ommit the alias thanks to autoaliasing for single-services from your code.

# services.yml

services:
    _defaults:
        autowire: true

    ApiExceptionBundle\: ~
        resource: ../ # path to ApiExceptionBundle directory
Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115