Reputation: 12418
I'd like to create my own custom resource in a Sylius application as described here. After many pitfalls and errors as described blow I looked also at some Sylius plugins and found this one, where everything works fine.
However, following Docs and such examples won't work in my cases.
I have defined the resource this way:
resources.yml
:
app.custody:
driver: doctrine/orm
classes:
model: AppBundle\Entity\CustodyWallet
form: AppBundle\Form\Type\CustodyType
controller: AppBundle\Controller\Shop\CustodyController
routing.yml
:
account_token_custody:
path: /account/custody
methods: [GET, POST]
defaults:
_controller: app.controller.custody:custodyAction
_sylius:
template: "@AppBundle/custody.html.twig"
redirect: sylius_shop_account_dashboard
The CustodyController looks like this:
use AppBundle\Entity\CustodyWallet;
use AppBundle\Form\Type\CustodyType;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class CustodyController extends ResourceController
{
public function custodyAction(Request $request): Response
{
// .... code .....
}
}
However, it results in the following error:
Cannot autowire service "AppBundle\Controller\Shop\CustodyController": argument "$metadata" of method "Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct()" references interface "Sylius\Component\Resource\Metadata\MetadataInterface" but no such service exists. Did you create a class that implements this interface?
Searching for this error sent me to this GitHub issue, where people recommend to set autowire to false for this particular Controller. So I did:
services.yml:
AppBundle\Controller\Shop\CustodyController:
autowire: false
public: true
But this way the constructor is called without any arguments:
Too few arguments to function Sylius\Bundle\ResourceBundle\Controller\ResourceController::__construct(), 0 passed in /var/www/var/cache/dev/Container1MQRWcB/getCustodyControllerService.php on line 16 and exactly 17 expected
I'm curious why a similar configuration works in the CmsPlugin which I have mentioned above but not in my case.
How can I achieve that?
Upvotes: 0
Views: 2781
Reputation: 517
Based on this configuration
sylius_resource:
resources:
app.custody:
driver: doctrine/orm
classes:
model: AppBundle\Entity\CustodyWallet
controller: AppBundle\Controller\Shop\CustodyController
Sylius will generate a few services, including the resource controller, as per resource bundle documentation
Just define the controller class and it will define the service and will wire the right contructor arguments.
In this case, it will generate a service with id app.controller.custody
, which definition can be seen by running php bin/console debug:container app.controller.custody
.
Then, in services.yaml
there's this configuration
AppBundle\Controller\Shop\CustodyController:
autowire: false
public: true
which defines another service with id AppBundle\Controller\Shop\CustodyController
that's not processed by Sylius.
Even if that configuration is removed, the error will still be there because there's an automatic service loading configured, here's another example of it on the same page.
The solution is simple: exclude resource controllers from that import:
# config/services.yaml
services:
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,CustodyController.php}'
If there are many resource controllers and/or potentially more to be added, then it might be easier to put them in a common folder and add it to the exlude glob pattern, like:
# config/services.yaml
services:
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php,ResourceController}'
Upvotes: 2