2
votes

Service "sylius.repository.product" not found: even though it exists in the app's container, the container inside "App\Controller\Shop\SubscribeBoxController" is a smaller service locator that only knows about the "doctrine", "form.factory", "http_kernel", "parameter_bag", "request_stack", "router", "security.authorization_checker", "security.csrf.token_manager", "security.token_storage", "serializer", "session", "templating" and "twig" services. Try using dependency injection instead.

I got this error when I am trying to use the sylius services on my controller:

public function index(Request $request)
{
    $subscribed = new Subscribed();
    $subscribeForm = $this->createForm(SubscribeType::class, $subscribed);
    $subscribeForm->handleRequest($request);

    if ($subscribeForm->isSubmitted() && $subscribeForm->isValid()) {
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($subscribed);
        $entityManager->flush();

        return $this->redirectToRoute('subscribe_details');
    }

    /** @var ProductRepository $productRepository */
    $productRepository = $this->get('sylius.repository.product');
    $product = $productRepository->findAll();

    return $this->render('@SyliusShop/Subscribe/plan.html.twig', [
        'form' => $subscribeForm->createView(),
        'product' => $product,
    ]);
}

So if anyone knows about this error let me know! :)

2
Have you tried using dependency injection instead?Jonnix
Yes but I have this new error:Matheo
Cannot autowire argument $productRepository of "App\Controller\Shop\SubscribeBoxController::details()": it references class "Sylius\Bundle\ProductBundle\Doctrine\ORM\ProductRepository" but no such service exists. You should maybe alias this class to one of these existing services: "sylius.repository.product", "App\Repository\ProductRepository".Matheo
So, if you start to use autowiring, what have you configured for your custom application code?Nico Haase
I can't find out what I should configure ...Matheo

2 Answers

3
votes

Symfony seems to be moving away from direct service container access and towards using dependency injection to get services inside controllers. Also, Sylius embraes this fully -- most of their own controllers don't even extend the older base Symfony controllers.

There's two things you can try. First, if you want to access services directly from the service container (AND those services are public), you can inject an instance of the service container in your constructor.

private $fullServiceContainer;
public function __construct(
    \Symfony\Component\DependencyInjection\ContainerInterface $container
) {
    $this->fullServiceContainer = $container;
}

//...
$this->fullServiceContainer->get('sylius.repository.product')

Second, you can inject the service yourself if the service has a name or alias that looks like a PHP class. I see that the sylius.repository.product service exists in the container

$ php bin/console debug:container sylius.repository.product

Information for Service "sylius.repository.product"
===================================================

 ---------------- --------------------------------------------------------- 
  Option           Value                                                    
 ---------------- --------------------------------------------------------- 
  Service ID       sylius.repository.product                                
  Class            Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository  
  Tags             -                                                        
  Public           yes                                                      
  Synthetic        no                                                       
  Lazy             no                                                       
  Shared           yes                                                      
  Abstract         no                                                       
  Autowired        no                                                       
  Autoconfigured   no                                                       
 ---------------- --------------------------------------------------------- 

but its class -- Sylius\Bundle\CoreBundle\Doctrine\ORM\ProductRepository does not appear to be linked to a service.

$ php bin/console debug:container ProductRepository                                                     
  No services found that match "ProductRepository".  

This means if you want to inject the product repository you'll need to create an alias in your own Symfony application, and this starts to get outside the scope of a single Stack Overflow answer.

Two articles (self links) that might be of interest to you if you want to wrap your head around Sylius/Symfony and the service container.

Symfony’s Service Container

Symfony: Autowiring Services https://alanstorm.com/symfonys-service-container/

0
votes

You should use dependency injection, with RepositoryInterface and named parameter $productRepository.

Sylius declares autowiring in this way.

use Sylius\Component\Resource\Repository\RepositoryInterface;

final class MyClass
{
    public function __construct(
        private RepositoryInterface $productRepository
    ) {
    }
}

See \Sylius\Bundle\ResourceBundle\DependencyInjection\Driver\Doctrine\DoctrineORMDriver for more details