Closed alejgr closed 2 years ago
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.
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:
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