Skip to content

Conversation

@shyim
Copy link
Member

@shyim shyim commented Feb 11, 2026

No description provided.

@shyim shyim marked this pull request as draft February 11, 2026 10:34

Before we're going to have a look at some examples, we need to register our new service to the [Dependency Injection](../../plugin-fundamentals/dependency-injection) container.
Please make sure to add the `shopware.payment.method` tag to your service definition, otherwise Shopware won't recognize your service as a payment handler.
Use the `#[AutoconfigureTag('shopware.payment.method')]` attribute on your handler class, otherwise Shopware won't recognize it as a payment handler.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this not work automatically in this case? above you wrote, because we are extending a certain abstract class, we do not need to set the attribute 🤔

After we've created our customized payment provider class, we have to register it to the DI-container via the `services.xml`.
With autowiring enabled, the `#[AsDecorator]` attribute on the class is sufficient to register the decorator. No explicit service configuration is needed.

::: code-group
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should not remove the ::: code-group stuff. also on other pages


</Tab>
</Tabs>
With `autoconfigure` enabled in your `services.php`, the subscriber is automatically registered because it implements `EventSubscriberInterface` — no additional configuration is needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enabled in your "services.php" this is missing in some of the texts above. you should recheck them

</services>
</container>
```
After we've created our subscriber, it needs to be registered. With `autoconfigure` enabled in your `services.php`, the subscriber is automatically registered because it implements `EventSubscriberInterface` — no additional configuration is needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
After we've created our subscriber, it needs to be registered. With `autoconfigure` enabled in your `services.php`, the subscriber is automatically registered because it implements `EventSubscriberInterface` — no additional configuration is needed.
After we've created our subscriber, it needs to be registered. With `autoconfigure` enabled in your `services.php`, the subscriber is automatically registered because it implements `EventSubscriberInterface`

no additional configuration is needed. I think, this part or similar occurences of this sentence can be removed everywhere

</services>
</container>
```
So let's inject this repository into our class called `ReplacingData`. With `autowire` enabled in your `services.php`, the repositories are automatically injected into the constructor — no additional configuration is needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
So let's inject this repository into our class called `ReplacingData`. With `autowire` enabled in your `services.php`, the repositories are automatically injected into the constructor — no additional configuration is needed.
With `autowire` enabled in your `services.php`, the repositories are automatically injected into the constructor of the class called `ReplacingData`.

```

So we registered a custom service called `WritingData` and applied the repositories as a constructor parameter. If you want to fetch data for another entity, just switch the `id` in the `services.xml` to whatever repository you need, e.g. `order.repository` for orders.
So we registered a custom service called `WritingData` and applied the repositories as constructor parameters. If you want to work with another entity, just change the type-hint in the constructor to the repository you need. The repository naming convention is `entity_name.repository`, e.g. `order.repository` for orders.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is correct. if you need another repository, you need to use the autowire attribute and need to state which repo you want to inject

The last step is creating our decorated service called `ExampleServiceDecorator` in this example. Our decorated service has to extend from the `AbstractExampleService` and the constructor has to accept an instance of `AbstractExampleService`. Furthermore, the `getDecorated()` function has to return the decorated service passed into the constructor.

Your service could then look like below:
The `#[AsDecorator]` attribute replaces the need for any XML or PHP service configuration for the decoration:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The `#[AsDecorator]` attribute replaces the need for any XML or PHP service configuration for the decoration:
The `#[AsDecorator]` attribute defines which class should be decorated:

</container>
```
With autowire and autoconfigure enabled, both services are registered automatically:
- `ProductCountRoute` receives `product.repository` via autowire
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repos will not work automatically, right?

Using a `JsonResponse` instead of a normal `Response` causes the data structures passed to it to be automatically turned into a `JSON` string.

The following `services.xml` and `routes.xml` are identical as in the before mentioned article, but here they are for reference anyway:
The controller is automatically registered via autowiring. The `routes.xml` is identical as in the before mentioned article, but here it is for reference anyway:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

controller need to be configured in the services.php because they need to be public

@JoshuaBehrens
Copy link
Contributor

Is this really something we want to have promoted? It feels like the number of bundles (not important whether plugin, shopware bundle or plugin bundle) makes building the container worse due to autowiring. Checks like this (although very plugin specific) that enforce to use autoloading:
https://github.com/shopware/shopware/blob/4e0c0f700e38dd086dd7727554c762b45ec50bde/src/Core/Framework/Plugin/KernelPluginLoader/KernelPluginLoader.php#L135-L153
Which - last time I checked within projects - is only used by SwagPayPal for a single function:
https://github.com/shopware/SwagPayPal/blob/47f88589457c996d4d6b27886d4904d6630fb674/src/SwagPayPal.php#L87-L91
is super annoying to have when it is not even used but takes up performance to check for every function a plugin has. And it is not about the function the plugin class implements. The base class has also a lot of functions. And this is only the tip of my last research why building takes up so much time.

Please do not promote autowiring when complex projects are not feasable with this. One shall not have to fear clearing the cache due to container building. I prefer writing hard-wired services.php files over magic, that I did not understand why it worked. Attributes are a nice way to keep services.php away but takes so much building time. Please do not become Laravel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants