8p / EightPointsGuzzleBundle

⛽️ Integrates Guzzle 6.x, a PHP HTTP Client, into Symfony
MIT License
440 stars 71 forks source link

Get EntityManager in guzzle plugin #311

Closed notresponding2u closed 2 years ago

notresponding2u commented 3 years ago

| Symfony version | 5.3.6 | Guzzle version | 8.2

I am trying to make a guzzle plugin, for all clients. Which logs the requests.

What I am trying to do, is to get the EntityManager in the plugin and pass it to the middleware. This is probably the wrong approach, and this is what I need help with - how to get the entity manager in the middleware.

So far I get this error when I try to get the entity manager from the container object in the plugin:

You have requested a non-existent service "doctrine.orm.default_entity_manager".

What I want is to use the entity manager into the middleware, to be able to save a log entry. How to do that?

Here is the conf for guzzle:

eight_points_guzzle:
  clients:
    default:
      plugin:
        logging: ~

Here is the plugin:

class LoggingPlugin extends Bundle implements PluginInterface {

  /**
   * @return string
   */
  public function getPluginName(): string {
    return 'logging';
  }

  public function addConfiguration(ArrayNodeDefinition $pluginNode): void {
  }

  public function load(array $configs, ContainerBuilder $container): void {
    // TODO: Implement load() method.
  }

  public function loadForClient(array $config, ContainerBuilder $container, string $clientName, Definition $handler): void {
    // Create DI definition of middleware.
    $middleware = new Definition(LoggingMiddleware::class);

    $em = $container->get('doctrine.orm.default_entity_manager');
    $middleware->setArguments([$em]);
    $middleware->setPublic(TRUE);

    // Register Middleware as a Service.
    $middlewareServiceName = sprintf('guzzle_bundle_logging_plugin.middleware.%s', $clientName);
    $container->setDefinition($middlewareServiceName, $middleware);

    // Inject this service to given Handler Stack.
    $middlewareExpression = new Expression(sprintf('service("%s")', $middlewareServiceName));
    $handler->addMethodCall('unshift', [$middlewareExpression]);
  }
}

And here is the middleware:

class LoggingMiddleware  {

  private EntityManager $entityManager;

  public function __construct(EntityManager $entityManager) {
    $this->entityManager = $entityManager;
  }

  public function __invoke(callable $handler) {
    return function (RequestInterface $request, array $options) use ($handler) {
      $logging = new Logging();
      $logging->setLog($request->getUri());

      $this->entityManager->persist($logging);
      $this->entityManager->flush($logging);
    };
  }
}

Here is a test that I use to try it out:

class TestPlugin extends KernelTestCase{
  public function test1(){
    $em = $this->getContainer()->get('doctrine.orm.default_entity_manager');

    $client = $this->getContainer()->get('eight_points_guzzle.client.default');

    $result = $client->request('GET', 'https://google.com');

    $this->assertTrue(TRUE);
  }
}

Here we get the entity manager, but we fail in the plugin itself. It looks it can't figure out the configs.

Also link to the whole project here

rpkamp commented 2 years ago

IMO This bundle shouldn't be tied to Doctrine directly. It should log to monolog (which it already does) and then Monolog should be set up to write to Doctrine.

That way it's a lot easier to switch where to log to without having to change anything in the Guzzle Middleware.