roach-php / core

The complete web scraping toolkit for PHP.

Home Page:https://roach-php.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

League Container and Symfony container conflicts

alejgarciarodriguez opened this issue · comments

I am using in roach-php in a Symfony 6 project. I am trying to inject the EntityManagerInterface in my ItemProcessorInterface class to save the object in the DB. But doing that looks like it creates some kind of conflict between the containers:

Alias (Doctrine\ORM\EntityManagerInterface) is not being managed by the container or delegates
in (League) Container.php, 188

This is happening also if I inject dependencies in the Spider class. Any workaround for this? Maybe telling symfony to ignore these classes and using League Container instead? No idea how to do that since league container is instantiated in vendor/roach-php

Ok I didn't read all the doc lol. Here is the answer

https://roach-php.dev/docs/dependency-injection/#swapping-out-the-container

We can close this :)

Ok so now the problem is, its not working because Roach now uses Symfony container even for loading their own classes and they are not loaded by Symfony since they're in vendor directory,

You have requested a non-existent service "RoachPHP\Core\Engine".

I think we need a bundle for this then

Yeah, that’s essentially what the framework integrations would have to do (that’s what the Laravel package does). Mostly providing a bunch of container bindings. I do want to provide a first-party Symfony package eventually, but I’m not super familiar with the Symfony ecosystem and I’ve never written a bundle before, so it’s been going a bit slow.

I could make it work by creating a bundle, but now I found some issues... services must be public since Roach library are getting them directly via container ($container->get()). Even the services in the userland (MySpider in the examples)

So I need to create some tags:

# RoachPHP\Bundle\DependencyInjection
class RoachPHPExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        // bindings go here

        $container->registerForAutoconfiguration(SpiderInterface::class)
            ->addTag('roach.spider');

        $container->registerForAutoconfiguration(ItemProcessorInterface::class)
            ->addTag('roach.item_processor');

        // extensions middlewares etc
    }
}

And a compiler pass:

// RoachPHP\Bundle\DependencyInjection\Compiler
class RoachCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
         // does the trick and inject the container even if its a static method
         $container
            ->getDefinition(Roach::class)
            ->addMethodCall('useContainer', [new Reference('service_container')])
            ->setPublic(true);

        foreach ($container->findTaggedServiceIds('roach.spider') as $id => $tags) {
            $container->getDefinition($id)->setPublic(true);
        }

        foreach ($container->findTaggedServiceIds('roach.item_processor') as $id => $tags) {
            $container->getDefinition($id)->setPublic(true);
        }

        foreach ($container->findTaggedServiceIds('roach.extension') as $id => $tags) {
            $container->getDefinition($id)->setPublic(true);
        }
    }
}

Not sure if its a good practice to do that in a symfony bundle, probably not

This is my symfony console command:

class AppCommand extends Command
{
    public function __construct(private Roach $roach)
    {
        parent::__construct();
    }
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        Roach::startSpider(MySpider::class);
        return Command::SUCCESS;
    }
}

Or creating a Roach service in the bundle, as a wrapper for the actual Roach static class and do something like $roach->startSpider(MySpider::class)

I wrote a bundle for Symfony.
Now you can plug it in through the composer.
https://github.com/Ne-Lexa/roach-php-bundle

That looks really nice. Good job! I’ll add it to the docs shortly 👍

I added a link to the repo to the docs. I assume the bundle fixes this issue so I'll close it for now.