0

I'm using some Symfony components (Not the framework) and I am trying to inject a dependency in a controller that I have defined as a service, however I'm getting a Fatal 'Too few arguments error', as the dependencies are not being injected.

My components are version 4.2.

My index.php (Front Controller)

<?php

require_once(__DIR__ . '/../vendor/autoload.php');

use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;

require_once('../config.php');
require_once('containerBuilder.php');

$fileLocator = new FileLocator([__DIR__]);
$loader = new YamlFileLoader($fileLocator);
$routes = $loader->load('routes.yml');
$request = Request::createFromGlobals();
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$controllerResolver = new HttpKernel\Controller\ControllerResolver();
$argumentResolver = new HttpKernel\Controller\ArgumentResolver();

try {
  $request->attributes->add($matcher->match($request->getPathInfo()));
  $controller = $controllerResolver->getController($request);
  $arguments = $argumentResolver->getArguments($request, $controller);
  $response = call_user_func_array($controller, $arguments);
} catch (ResourceNotFoundException $e) {
  $response = new Response('Not Found', 404);
} catch (Exception $e) {
  $response = new Response('An error occurred', 500);
}
$response->send();

services.yml

services:
  api_connection.rezdy:
      class: \Site\ApiConnection\RezdyApiConnection
      arguments: []
  controller.api_controller:
      class: \Site\Controller\ApiController
      arguments: ['@api_connection.rezdy']

routes.yml

products:
    path: /products
    defaults: { _controller: '\Site\Controller\ApiController::getProducts' }
product:
    path: /products/{id}
    defaults: { _controller: '\Site\Controller\ApiController::index' }

ApiController.php

    <?php

    namespace Site\Controller;

    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\Yaml\Yaml;
    use Site\ApiConnection\ApiConnectionInterface;

    class ApiController {

      private $connection;

      public function __construct(ApiConnectionInterface $connection) {
        $this->connection = $connection;
      }

      public function getProducts() {
        $details = Yaml::parseFile(WEB_ROOT . '/api_connection_details.yml');
        return new JsonResponse('This is dog');
      }

    }


chap
  • 1,860
  • 5
  • 24
  • 39
  • Have you tried `'\Site`→ `'Site`? Also, `services: > _defaults: > autowire: true`? – Tomas Votruba Feb 03 '19 at 11:32
  • Your controller resolver has no knowledge of the container hence it will just new the controller. Gonna take a bit more work to integrate the container. Maybe take a look at the framework bundle's ControllerResolver for some ideas. – Cerad Feb 03 '19 at 14:48
  • 1
    There is also a HttpKernel\Controller\ContainerControllerResolver that might help. – Cerad Feb 03 '19 at 14:55
  • Yes @Cerad I managed to find the ContainerControllerResolver and also changed my service ids to be fully qualified classes and it's working. I will post the solution tonight. – chap Feb 03 '19 at 22:47

1 Answers1

0

As mentioned in the comments, I had to use ContainerControllerResolver instead of ControllerResolver and I also needed to update the service ids to be fully qualified domain names. I also started using the HttpKernel to handle the controller logic.

index.php

require_once(__DIR__ . '/../vendor/autoload.php');

use Symfony\Component\Config\FileLocator;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Site\Site;

require_once('../config.php');
require_once('containerBuilder.php');

$fileLocator = new FileLocator([__DIR__]);
$loader = new YamlFileLoader($fileLocator);
$routes = $loader->load('routes.yml');
$request = Request::createFromGlobals();
$requestStack = new RequestStack();
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($routes, $context);
$controllerResolver = new HttpKernel\Controller\ContainerControllerResolver($container);
$argumentResolver = new HttpKernel\Controller\ArgumentResolver();
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new HttpKernel\EventListener\RouterListener($matcher, $requestStack));
$site = new Site($dispatcher, $controllerResolver, $requestStack, $argumentResolver);
$response = $site->handle($request);
$response->send();

services.yml

services:
  \Site\ApiConnection\RezdyApiConnection:
      class: \Site\ApiConnection\RezdyApiConnection
      arguments: []
  \Site\Controller\ApiController:
      class: \Site\Controller\ApiController
      arguments: ['@\Site\ApiConnection\RezdyApiConnection']
chap
  • 1,860
  • 5
  • 24
  • 39