From 49d18c70c3476d9d76970e174178849e442c743d Mon Sep 17 00:00:00 2001 From: umut Date: Mon, 2 Mar 2026 15:45:45 +0100 Subject: [PATCH 1/7] chore: use php configs in DI examples --- .../plugins/checkout/cart/add-cart-items.md | 52 ++-- .../checkout/cart/add-cart-validator.md | 26 +- .../checkout/cart/change-price-of-item.md | 38 +-- .../cart/customize-price-calculation.md | 32 ++- .../plugins/checkout/cart/tax-provider.md | 24 +- .../document/add-custom-document-type.md | 63 +++-- .../checkout/payment/add-payment-plugin.md | 227 ++++++++++-------- .../payment/customize-payment-provider.md | 32 ++- .../content/cms/add-data-to-cms-elements.md | 23 +- .../plugins/content/mail/add-data-to-mails.md | 58 +++-- .../media/add-custom-file-extension.md | 30 +-- ...-media-files-referenced-in-your-plugins.md | 30 +-- .../plugins/content/seo/add-custom-seo-url.md | 71 +++--- .../plugins/content/seo/extend-robots-txt.md | 85 ++++--- .../sitemap/add-custom-sitemap-entries.md | 42 ++-- .../content/sitemap/modify-sitemap-entries.md | 67 +++--- .../implementing-your-own-stock-storage.md | 36 +-- ...stock-information-from-different-source.md | 36 +-- ...oduct-entity-extension-to-elasticsearch.md | 71 +++--- .../custom-field/add-custom-field.md | 36 +-- .../fetching-data-from-entity-selection.md | 60 ++--- .../add-complex-data-to-existing-entities.md | 94 ++++---- .../data-handling/add-custom-complex-data.md | 24 +- .../data-handling/add-data-indexer.md | 67 +++--- .../data-handling/add-data-translations.md | 42 ++-- .../framework/data-handling/reading-data.md | 28 ++- .../replacing-associated-data.md | 32 +-- .../data-handling/using-database-events.md | 31 ++- .../framework/data-handling/writing-data.md | 34 +-- .../plugins/framework/event/finding-events.md | 33 +-- .../framework/filesystem/filesystem.md | 42 ++-- .../store-api/add-store-api-route.md | 64 ++--- .../store-api/override-existing-route.md | 40 +-- .../plugin-fundamentals/add-custom-service.md | 66 ++--- .../plugin-fundamentals/add-scheduled-task.md | 54 +++-- .../plugin-fundamentals/adjusting-service.md | 33 +-- .../dependency-injection.md | 26 +- .../listening-to-events.md | 35 ++- .../use-plugin-configuration.md | 32 +-- .../storefront/add-cookie-to-manager.md | 31 ++- .../storefront/add-custom-controller.md | 36 +-- .../storefront/add-data-to-storefront-page.md | 75 +++--- .../add-dynamic-content-via-ajax-calls.md | 32 +-- .../add-scss-variables-via-subscriber.md | 61 ++--- .../b2b-suite/guides/core/overload-classes.md | 170 +++++++------ .../how-to-extend-the-storefront.md | 28 ++- 46 files changed, 1259 insertions(+), 1090 deletions(-) diff --git a/guides/plugins/plugins/checkout/cart/add-cart-items.md b/guides/plugins/plugins/checkout/cart/add-cart-items.md index e2affd8092..9e680e1d00 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-items.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-items.md @@ -100,19 +100,19 @@ Sometimes you really want to have a custom line item handler, e.g. for your own You need to create a new class which implements the interface `\Shopware\Core\Checkout\Cart\LineItemFactoryHandler\LineItemFactoryInterface` and it needs to be registered in the DI container with the tag `shopware.cart.line_item.factory`. -```xml -// /src/Resources/config/services.xml - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExampleHandler::class) + ->tag('shopware.cart.line_item.factory'); +}; ``` Let's first have a look at an example handler: @@ -199,17 +199,21 @@ As you can see, this processor takes an "original cart" as an input and adds all Of course you can use processors to do much more than this. Have a look at [adding cart processors and collectors](./add-cart-processor-collector). -Now register this processor in your `services.xml` like this: - -```html -// /Resources/config/services.xml -... - - ... - - - - +Now register this processor in your `services.php` like this: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExampleProcessor::class) + ->tag('shopware.cart.processor', ['priority' => 4800]); +}; ``` And that's it. You should now be able to create line items of type `example`. diff --git a/guides/plugins/plugins/checkout/cart/add-cart-validator.md b/guides/plugins/plugins/checkout/cart/add-cart-validator.md index 940c78b434..506fae05f8 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-validator.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-validator.md @@ -76,19 +76,19 @@ One more thing to do is to register your new validator to the [dependency inject Your validator has to be registered using the tag `shopware.cart.validator`: -```xml -// /src/Resources/config/services.xml - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomCartValidator::class) + ->tag('shopware.cart.validator'); +}; ``` ### Adding the custom cart error diff --git a/guides/plugins/plugins/checkout/cart/change-price-of-item.md b/guides/plugins/plugins/checkout/cart/change-price-of-item.md index 49cbce65b6..946b821ed6 100644 --- a/guides/plugins/plugins/checkout/cart/change-price-of-item.md +++ b/guides/plugins/plugins/checkout/cart/change-price-of-item.md @@ -263,23 +263,27 @@ One last thing, we need to register our processor and collector to the DI contai Let's have a look at it: -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(OverwritePriceCollector::class) + ->args([ + service(QuantityPriceCalculator::class), + ]) + // after product collector/processor + ->tag('shopware.cart.processor', ['priority' => 4500]) + ->tag('shopware.cart.collector', ['priority' => 4500]); +}; ``` And that's it. Your processor / collector should now be working. diff --git a/guides/plugins/plugins/checkout/cart/customize-price-calculation.md b/guides/plugins/plugins/checkout/cart/customize-price-calculation.md index bca121a75a..a793082603 100644 --- a/guides/plugins/plugins/checkout/cart/customize-price-calculation.md +++ b/guides/plugins/plugins/checkout/cart/customize-price-calculation.md @@ -81,19 +81,25 @@ Most likely you also want to narrow down which product's prices you want to edit Do not forget to actually register your decoration to the service container, otherwise it will not have any effect. -```xml -// /src/Resources/config/services.xml - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomProductPriceCalculator::class) + ->decorate(ProductPriceCalculator::class) + ->args([ + service('.inner'), + ]); +}; ``` ## Next steps diff --git a/guides/plugins/plugins/checkout/cart/tax-provider.md b/guides/plugins/plugins/checkout/cart/tax-provider.md index 1823b921c4..3fd9d9683a 100644 --- a/guides/plugins/plugins/checkout/cart/tax-provider.md +++ b/guides/plugins/plugins/checkout/cart/tax-provider.md @@ -83,21 +83,21 @@ class TaxProvider extends AbstractTaxProvider ## Registering the tax provider in the DI container -After you have created your tax provider, you need to register it in the DI container. To do so, you need to create a new service in the `services.xml` file and tag the service as `shopware.tax.provider`. +After you have created your tax provider, you need to register it in the DI container. To do so, you need to create a new service in the `services.php` file and tag the service as `shopware.tax.provider`. -```xml -// /src/Resources/config/services.xml - +```php +// /src/Resources/config/services.php + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - + $services->set(TaxProvider::class) + ->tag('shopware.tax.provider'); +}; ``` ## Migrate your tax provider to the database diff --git a/guides/plugins/plugins/checkout/document/add-custom-document-type.md b/guides/plugins/plugins/checkout/document/add-custom-document-type.md index 0b4bafda5d..c373729a3a 100644 --- a/guides/plugins/plugins/checkout/document/add-custom-document-type.md +++ b/guides/plugins/plugins/checkout/document/add-custom-document-type.md @@ -341,14 +341,20 @@ Here's what the function does: The service definition for our custom renderer would look like this: -```xml - - - - - - - +```php +use Shopware\Core\Checkout\Document\Service\DocumentConfigLoader; +use Shopware\Core\Checkout\Document\Service\DocumentFileRendererRegistry; +use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface; +use Swag\BasicExample\Core\Checkout\Document\Render\ExampleDocumentRenderer; + +$services->set(ExampleDocumentRenderer::class) + ->args([ + service('order.repository'), + service(DocumentConfigLoader::class), + service(NumberRangeValueGeneratorInterface::class), + service(DocumentFileRendererRegistry::class), + ]) + ->tag('document.renderer'); ``` ### Adding a file type renderer @@ -358,26 +364,33 @@ Depending on the file type we either get the content with `$this->fileRendererRe ### Registering the renderer in the service container -Now we need to register our custom `ExampleDocumentRenderer` in the service container. Create or update your `services.xml` file: +Now we need to register our custom `ExampleDocumentRenderer` in the service container. Create or update your `services.php` file: ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - - - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(ExampleDocumentRenderer::class) + ->args([ + service('order.repository'), + service(DocumentConfigLoader::class), + service(NumberRangeValueGeneratorInterface::class), + service(DocumentFileRendererRegistry::class), + ]) + ->tag('document.renderer'); +}; ``` ::: diff --git a/guides/plugins/plugins/checkout/payment/add-payment-plugin.md b/guides/plugins/plugins/checkout/payment/add-payment-plugin.md index 4b515c128f..905c0c71a0 100644 --- a/guides/plugins/plugins/checkout/payment/add-payment-plugin.md +++ b/guides/plugins/plugins/checkout/payment/add-payment-plugin.md @@ -39,19 +39,20 @@ Please make sure to add the `shopware.payment.method` tag to your service defini We'll use a class called `MyCustomPaymentHandler` here. -```xml [/src/Resources/config/services.xml] - - - - - - - - - - +```php [/src/Resources/config/services.php] +services(); + + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method'); +}; ``` Now, let's start with the actual examples. @@ -116,20 +117,24 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler } ``` -```xml [services.xml] - +```php [services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - - + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method') + ->args([ + service(OrderTransactionStateHandler::class), + ]); +}; ``` ::: @@ -227,20 +232,24 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler } ``` -```xml [services.xml] - +```php [services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - - + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method') + ->args([ + service(OrderTransactionStateHandler::class), + ]); +}; ``` ::: @@ -350,7 +359,7 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler // In here you should probably call your payment provider to precess the payment // $this->myPaymentProvider->processPayment($transaction); - + // afterward you should update the transaction with the new state $this->transactionStateHandler->process($transaction->getOrderTransactionId(), $context); @@ -359,20 +368,24 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler } ``` -```xml [services.xml] - +```php [services.php] + +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; - - - - - - - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); + + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method') + ->args([ + service(OrderTransactionStateHandler::class), + ]); +}; ``` ::: @@ -489,22 +502,27 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler ``` -```xml [services.xml] - - - - - - - - - - - - - +```php [services.php] +services(); + + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method') + ->args([ + service('order_transaction_capture_refund.repository'), + service(OrderTransactionStateHandler::class), + service(OrderTransactionCaptureStateHandler::class), + ]); +}; ``` ::: @@ -567,16 +585,16 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler // In here you should probably call your payment provider to create a billing agreement // $this->myPaymentProvider->createBillingAgreement($transaction); } - + // Don't forget to capture the initial payment as well // $this->myPaymentProvider->processPayment($transaction); - + // afterward you should update the transaction with the new state $this->transactionStateHandler->process($transaction->getOrderTransactionId(), $context); return null; } - + /** * call your PSP here for capturing a recurring payment * a valid billing agreement between the customer and the PSP should usually already be in place @@ -602,20 +620,24 @@ class MyCustomPaymentHandler extends AbstractPaymentHandler ``` -```xml [services.xml] - +```php [services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - - + $services->set(MyCustomPaymentHandler::class) + ->tag('shopware.payment.method') + ->args([ + service(OrderTransactionStateHandler::class), + ]); +}; ``` ::: @@ -695,7 +717,7 @@ class SwagBasicExample extends Plugin 'name' => 'Example payment', 'description' => 'Example payment description', 'pluginId' => $pluginId, - // if true, payment method will also be available after the order + // if true, payment method will also be available after the order // is created, e.g. if payment fails and the user wants to try again 'afterOrderEnabled' => true, // the technicalName helps you to identify the payment method uniquely @@ -784,27 +806,26 @@ Remove any other occurrences of the following tags: ::: code-group -```xml [services.xml] - - - - - - - - - - - - - - - - - - +```php [services.php] +services(); + + $services->set(MyCustomPaymentHandler::class) + // this is the new tag for payment handlers + ->tag('shopware.payment.method') + + // remove any of these other tags + ->tag('shopware.payment.method.sync') + ->tag('shopware.payment.method.async') + ->tag('shopware.payment.method.prepared') + ->tag('shopware.payment.method.recurring') + ->tag('shopware.payment.method.refund'); +}; ``` ::: diff --git a/guides/plugins/plugins/checkout/payment/customize-payment-provider.md b/guides/plugins/plugins/checkout/payment/customize-payment-provider.md index 486d7e2d17..e3278b3798 100644 --- a/guides/plugins/plugins/checkout/payment/customize-payment-provider.md +++ b/guides/plugins/plugins/checkout/payment/customize-payment-provider.md @@ -24,7 +24,7 @@ First, we create a new class that extends from the provider we want to customise In this example we customise the class `Shopware\Core\Checkout\Payment\Cart\PaymentHandler\DebitPayment` and name our class `ExampleDebitPayment`. The constructor has to accept an instance of `OrderTransactionStateHandler` like the original service and additionally an instance of `DebitPayment` that we want to decorate. -After we've created our customized payment provider class, we have to register it to the DI-container via the `services.xml`. +After we've created our customized payment provider class, we have to register it to the DI-container via the `services.php`. ::: code-group @@ -66,20 +66,26 @@ class ExampleDebitPayment extends DebitPayment } ``` -```xml [services.xml] - +```php [services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - - + $services->set(ExampleDebitPayment::class) + ->decorate(DebitPayment::class) + ->args([ + service(OrderTransactionStateHandler::class), + service('.inner'), + ]); +}; ``` ::: diff --git a/guides/plugins/plugins/content/cms/add-data-to-cms-elements.md b/guides/plugins/plugins/content/cms/add-data-to-cms-elements.md index b90d11d5fd..89449bf61c 100644 --- a/guides/plugins/plugins/content/cms/add-data-to-cms-elements.md +++ b/guides/plugins/plugins/content/cms/add-data-to-cms-elements.md @@ -60,23 +60,22 @@ In the previous [example](add-cms-element) we added a CMS element with the name As you can see the `getType` method of our custom resolver reflects that name by returning the `dailymotion` string. This resolver is called every time for an element of the type `dailymotion`. -To register our custom resolver to the service container, we have to register it in the `services.xml` file in our plugin. +To register our custom resolver to the service container, we have to register it in the `services.php` file in our plugin. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - +```php [PLUGIN_ROOT/src/Resources/config/services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - + $services->set(DailyMotionCmsElementResolver::class) + ->tag('shopware.cms.data_resolver'); +}; ``` ::: diff --git a/guides/plugins/plugins/content/mail/add-data-to-mails.md b/guides/plugins/plugins/content/mail/add-data-to-mails.md index cf117e5c11..91007874ff 100644 --- a/guides/plugins/plugins/content/mail/add-data-to-mails.md +++ b/guides/plugins/plugins/content/mail/add-data-to-mails.md @@ -78,22 +78,28 @@ If we add {{ myCustomData }} to any mail template, it should Of course you still have to register the decoration to the service container. Beware of the `decorates` attribute of our service. -Here's the respective example `services.xml`: +Here's the respective example `services.php`: ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(AddDataToMails::class) + ->decorate(MailService::class) + ->args([ + service('.inner'), + ]); +}; ``` ::: @@ -142,22 +148,22 @@ class MyMailSubscriber implements EventSubscriberInterface You have to register the subscriber to the service container as well. -Here's the respective example `services.xml`: +Here's the respective example `services.php`: ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(MyMailSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` ::: diff --git a/guides/plugins/plugins/content/media/add-custom-file-extension.md b/guides/plugins/plugins/content/media/add-custom-file-extension.md index ba4a44f79f..6149bded16 100644 --- a/guides/plugins/plugins/content/media/add-custom-file-extension.md +++ b/guides/plugins/plugins/content/media/add-custom-file-extension.md @@ -120,21 +120,21 @@ class CustomImageTypeDetector implements TypeDetectorInterface - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomImageTypeDetector::class) + ->tag('shopware.media_type.detector', ['priority' => 10]); +}; ``` diff --git a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md index 9dc1f3be32..fd032ace91 100644 --- a/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md +++ b/guides/plugins/plugins/content/media/prevent-deletion-of-media-files-referenced-in-your-plugins.md @@ -121,21 +121,21 @@ Make sure to register your event subscriber to the [Dependency injection contain by using the tag `kernel.event_subscriber`. - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(UnusedMediaSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` diff --git a/guides/plugins/plugins/content/seo/add-custom-seo-url.md b/guides/plugins/plugins/content/seo/add-custom-seo-url.md index 6e5f0cca55..310305b4f1 100644 --- a/guides/plugins/plugins/content/seo/add-custom-seo-url.md +++ b/guides/plugins/plugins/content/seo/add-custom-seo-url.md @@ -241,23 +241,27 @@ class ExamplePageSeoUrlRoute implements SeoUrlRouteInterface - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExamplePageSeoUrlRoute::class) + ->args([ + service(ExampleDefinition::class), + ]) + ->tag('shopware.seo_url.route'); +}; ``` @@ -335,24 +339,27 @@ class DynamicSeoUrlPageSubscriber implements EventSubscriberInterface - + + +```php +// /src/Resources/config/services.php +/src/Resources/config/services.xml - - +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; - - - - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - + $services->set(DynamicSeoUrlPageSubscriber::class) + ->args([ + service(SeoUrlUpdater::class), + ]) + ->tag('kernel.event_subscriber'); +}; ``` diff --git a/guides/plugins/plugins/content/seo/extend-robots-txt.md b/guides/plugins/plugins/content/seo/extend-robots-txt.md index 83abac59e5..ad759587b8 100644 --- a/guides/plugins/plugins/content/seo/extend-robots-txt.md +++ b/guides/plugins/plugins/content/seo/extend-robots-txt.md @@ -91,21 +91,26 @@ class RobotsExtensionListener - - -```XML - - - - - - - - - - + + +```php +services(); + + $services->set(RobotsExtensionListener::class) + ->args([ + service('logger'), + ]) + ->tag('kernel.event_listener', ['event' => RobotsDirectiveParsingEvent::class]); +}; ``` @@ -143,20 +148,21 @@ class CustomDirectiveListener - + -```XML - - +```php + - - - - - +use Shopware\Storefront\Page\Robots\Event\RobotsUnknownDirectiveEvent; +use Swag\Example\Listener\CustomDirectiveListener; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); + + $services->set(CustomDirectiveListener::class) + ->tag('kernel.event_listener', ['event' => RobotsUnknownDirectiveEvent::class]); +}; ``` @@ -243,20 +249,21 @@ class RobotsValidationListener - + + +```php + - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - + $services->set(RobotsValidationListener::class) + ->tag('kernel.event_listener', ['event' => RobotsDirectiveParsingEvent::class]); +}; ``` diff --git a/guides/plugins/plugins/content/sitemap/add-custom-sitemap-entries.md b/guides/plugins/plugins/content/sitemap/add-custom-sitemap-entries.md index 437eacc8ed..519eaa085b 100644 --- a/guides/plugins/plugins/content/sitemap/add-custom-sitemap-entries.md +++ b/guides/plugins/plugins/content/sitemap/add-custom-sitemap-entries.md @@ -168,25 +168,29 @@ class CustomUrlProvider extends AbstractUrlProvider - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomUrlProvider::class) + ->args([ + service('swag_example.repository'), + service(Connection::class), + service('router'), + ]) + ->tag('shopware.sitemap_url_provider'); +}; ``` diff --git a/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md b/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md index 6e1bebdf1a..b9fb206f89 100644 --- a/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md +++ b/guides/plugins/plugins/content/sitemap/modify-sitemap-entries.md @@ -94,22 +94,27 @@ class DecoratedProductUrlProvider extends AbstractUrlProvider - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(DecoratedProductUrlProvider::class) + ->decorate(ProductUrlProvider::class) + ->args([ + service('.inner'), + ]); +}; ``` @@ -169,21 +174,21 @@ class ProductSitemapQuerySubscriber implements EventSubscriberInterface - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ProductSitemapQuerySubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` diff --git a/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md b/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md index bab281f2c3..854f0b3dc2 100644 --- a/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md +++ b/guides/plugins/plugins/content/stock/implementing-your-own-stock-storage.md @@ -77,21 +77,27 @@ class StockStorageDecorator extends AbstractStockStorage - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(StockStorageDecorator::class) + ->decorate(StockStorage::class) + ->args([ + service('.inner'), + ]); +}; ``` diff --git a/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md b/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md index 95c89e4ae4..75c8647621 100644 --- a/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md +++ b/guides/plugins/plugins/content/stock/loading-stock-information-from-different-source.md @@ -75,21 +75,27 @@ class StockStorageDecorator extends AbstractStockStorage - - -```xml -// /src/Resources/config/services.xml - - - - - - - - - + + +```php +// /src/Resources/config/services.php +services(); + + $services->set(StockStorageDecorator::class) + ->decorate(StockStorage::class) + ->args([ + service('.inner'), + ]); +}; ``` diff --git a/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md b/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md index 74627021c4..b91ab70f41 100644 --- a/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md +++ b/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md @@ -23,39 +23,44 @@ We will extend the product extension with an `OneToOneAssociationField` and `One To extend the elasticsearch definition we need to extend the product definition first and add the subscriber. This is described in the above mentioned articles. Here we show you how this could look like in the end. -The service.xml with all needed definitions. - -```xml -// /src/Core/Content/DependencyInjection/product.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - +The services.php with all needed definitions. + +```php +// /src/Core/Content/DependencyInjection/product.php +services(); + + $services->set(CustomExtension::class) + ->tag('shopware.entity.extension'); + + $services->set(OneToOneExampleExtensionDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'one_to_one_swag_example_extension']); + + $services->set(OneToManyExampleExtensionDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'one_to_many_swag_example_extension']); + + $services->set(ProductSubscriber::class) + ->tag('kernel.event_subscriber'); + + $services->set(MyProductEsDecorator::class) + ->decorate(ElasticsearchProductDefinition::class) + ->args([ + service(MyProductEsDecorator::class . '.inner'), + service(\Doctrine\DBAL\Connection::class), + ]); +}; ``` The product extension `CustomExtension.php` provides the extensions to the product entity. diff --git a/guides/plugins/plugins/framework/custom-field/add-custom-field.md b/guides/plugins/plugins/framework/custom-field/add-custom-field.md index 46a8a796e7..17d79ed13b 100644 --- a/guides/plugins/plugins/framework/custom-field/add-custom-field.md +++ b/guides/plugins/plugins/framework/custom-field/add-custom-field.md @@ -67,7 +67,7 @@ Now follows the important part. For this to work, you have to add the Data Abstr ```php // /src/Core/Content/Example/ExampleDefinition.php -use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; +use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; [...] class ExampleDefinition extends EntityDefinition @@ -130,7 +130,7 @@ Make sure to understand entity translations in general first, which is explained ```php // /src/Core/Content/Example/ExampleDefinition.php -use Shopware\Core\Framework\DataAbstractionLayer\Field\TranslatedField; +use Shopware\Core\Framework\DataAbstractionLayer\Field\TranslatedField; [...] @@ -158,7 +158,7 @@ In your translated entity definition, you then add the `CustomFields` field inst ```php // /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationDefinition.php -use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; +use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; [...] class ExampleTranslationDefinition extends EntityTranslationDefinition @@ -216,19 +216,21 @@ So now you've already filled the custom fields of one of your entity instances v Only if you want your custom field to show up in the Administration and to be editable in there, you have to define the custom fields first in a custom field set. For this you have to use the custom fieldset repository, which can be retrieved from the dependency injection container via the `custom_field_set.repository` key and is used like any other repository. -```xml - - - - - - - ... - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomFieldClass::class) + ->args([service('custom_field_set.repository')]); +}; ``` If you need to learn how that is done in full, head to our guide regarding [Writing data](../data-handling/writing-data). @@ -275,7 +277,7 @@ $this->customFieldSetRepository->create([ This will now create a custom field set with the name `swag_example_set` and the field, `swag_example_size`. This time we also define its type, which should be of type integer here. The type is important to mention, because the Administration will use this information to display a proper field. Also, when trying to write the custom field `swag_example_size`, the value has to be an integer. The translated labels are added to both the field and the set, which are going to be displayed in the Administration. Also, the fallback language can be defined in case the system language is not guaranteed to be either en_GB or de_DE. - + If you have several custom fields and want to order them within a specific order, you can do so with the `customFieldPosition` property. ::: info diff --git a/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md b/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md index 6876c300aa..c139a5dc42 100644 --- a/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md +++ b/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md @@ -50,22 +50,21 @@ class ProductSubscriber implements EventSubscriberInterface } ``` -For this subscriber to work we need to register it in the service container via the `services.xml` file: - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - +For this subscriber to work we need to register it in the service container via the `services.php` file: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ProductSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` Now our `ProductSubscriber` should be called every time a product is loaded, so we can resolve the custom field `custom_linked_product`. @@ -116,23 +115,24 @@ Inside the `onProductLoaded` method we can get access to the loaded product enti But, how we can load the linked product by its `id` if the custom field was set? We have to inject the product repository to achieve it. -First we update the `services.xml` and inject the product repository. +First we update the `services.php` and inject the product repository. + +```php +// /src/Resources/config/services.php +/src/Resources/config/services.xml - +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - - + $services->set(ProductSubscriber::class) + ->args([service('product.repository')]) + ->tag('kernel.event_subscriber'); +}; ``` Now we can use the product repository in our subscriber. diff --git a/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md b/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md index d7e1ff09d7..8af9c0e349 100644 --- a/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md +++ b/guides/plugins/plugins/framework/data-handling/add-complex-data-to-existing-entities.md @@ -57,22 +57,21 @@ class CustomExtension extends EntityExtension Now we have to register our extension via the DI-container. If you don't know how that's done in general, head over to our guide about registering a custom service [Add a custom class / service](../../plugin-fundamentals/add-custom-service) or our guide about the [dependency injection](../../plugin-fundamentals/dependency-injection). -Here's our `services.xml`: - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - +Here's our `services.php`: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(CustomExtension::class) + ->tag('shopware.entity.extension'); +}; ``` ### Adding a field with a database @@ -179,24 +178,23 @@ The fourth parameter is the class of the associated definition, the `ProductDefi Of course, this new definition also needs to be registered to the DI container: -```xml -// /src/Resources/config/services.xml - +```php +// /src/Resources/config/services.php + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - + $services->set(CustomExtension::class) + ->tag('shopware.entity.extension'); - - - - - + $services->set(ExampleExtensionDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'swag_example_extension']); +}; ``` #### Adding the new database table @@ -305,22 +303,21 @@ We're registering to the `ProductEvents::PRODUCT_LOADED_EVENT` event, which is f Please note that its second parameter, the actual value, has to be a struct and not just a string or other kind of scalar value. -After we've created our subscriber, we have to adjust our `services.xml` to register it. Below you can find our `services.xml`. +After we've created our subscriber, we have to adjust our `services.php` to register it. Below you can find our `services.php`. + +```php +// /src/Resources/config/services.php +/src/Resources/config/services.xml - +use Swag\BasicExample\Subscriber\ProductSubscriber; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - + $services->set(ProductSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` ## Entity extension vs. Custom fields @@ -361,10 +358,9 @@ class MyBulkExtension extends BulkEntityExtension Each yield defines the entity name which should be extended and the array value defines the fields which should be added. In this example, the `product` and `category` entities are extended. -You must also register the extension in your `services.xml` file and tag it with `shopware.bulk.entity.extension`. +You must also register the extension in your `services.php` file and tag it with `shopware.bulk.entity.extension`. -```xml - - - +```php +$services->set(\Examples\MyBulkExtension::class) + ->tag('shopware.bulk.entity.extension'); ``` diff --git a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md index bd8add32d3..15cf31b843 100644 --- a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md +++ b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md @@ -167,18 +167,18 @@ All that's left to do now, is to introduce your `ExampleDefinition` to Shopware Here's the `services.xml` as it should look like: -```xml - - - - - - - - - +```php +services(); + + $services->set(ExampleDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'swag_example']); +}; ``` Please note the tag for your definition and the respective `entity` attribute, which has to contain the technical name of your entity, which you provided in your entity definition. In this case this must be `swag_example`. diff --git a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md index bd53d3936e..1abeedc2cb 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md @@ -117,21 +117,27 @@ class ExampleIndexer extends EntityIndexer With the corresponding service registration: -```xml - - - - - - - - - - - - +```php +services(); + + $services->set(ExampleIndexer::class) + ->args([ + service(IteratorFactory::class), + service('customer.repository'), + service(Connection::class), + ]) + ->tag('shopware.entity_indexer'); +}; ``` The indexer service has to be tagged as `shopware.entity_indexer` in order to work. @@ -175,7 +181,7 @@ public function update(EntityWrittenContainerEvent $event): ?EntityIndexingMessa ## Index data using existing events -There are already a bunch of indexers in shopware that you can use. If you take a look at the `CustomerIndexer` or `CategoryIndexer` classes for example, you will see that they dispatch an event in the `handle` method. This should be used for indexing data of the main entities. Among others, the following indexers already exist and dispatch events that can be used for indexing data: +There are already a bunch of indexers in shopware that you can use. If you take a look at the `CustomerIndexer` or `CategoryIndexer` classes for example, you will see that they dispatch an event in the `handle` method. This should be used for indexing data of the main entities. Among others, the following indexers already exist and dispatch events that can be used for indexing data: * `CustomerIndexer` * `CategoryIndexer` @@ -248,19 +254,22 @@ class Subscriber implements EventSubscriberInterface The service definition for the subscriber would look like this. -```xml - - - - - - - - - - +```php +services(); + + $services->set(Subscriber::class) + ->args([service(Connection::class)]) + ->tag('kernel.event_subscriber'); +}; ``` It is recommended to work directly with the `Connection` since the event is dispatched in the context of an indexer. If we would use the Data Abstraction Layer \(DAL\) for writing changes to the database, the indexer would be triggered again, because it listens for `EntityWrittenContainerEvent` events. This would lead to an infinite loop. Using the `Connection` directly prevents the DAL from dispatching entity written events. Also the performance of plain sql is much higher, which is very important for indexers in general. diff --git a/guides/plugins/plugins/framework/data-handling/add-data-translations.md b/guides/plugins/plugins/framework/data-handling/add-data-translations.md index 73ada1fd6f..b5c60a8c3f 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-translations.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-translations.md @@ -133,27 +133,27 @@ class ExampleTranslationDefinition extends EntityTranslationDefinition As you can see, we've implemented a `StringField` for the `name` column, the other fields like the `language_id` will be automatically added by the `EntityTranslationDefinition` since they are base fields of it. -All that's left to do now, is to introduce your `ExampleTranslationDefinition` to Shopware by registering your class in your `services.xml` file and by using the `shopware.entity.definition` tag, because Shopware 6 is looking for definitions this way. Note, that we have to register the translation after the entity we want to translate. - -Here's the `services.xml` as it should look like: - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - - - +All that's left to do now, is to introduce your `ExampleTranslationDefinition` to Shopware by registering your class in your `services.php` file and by using the `shopware.entity.definition` tag, because Shopware 6 is looking for definitions this way. Note, that we have to register the translation after the entity we want to translate. + +Here's the `services.php` as it should look like: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExampleDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'swag_example']); + + $services->set(ExampleTranslationDefinition::class) + ->tag('shopware.entity.definition', ['entity' => 'swag_example_translation']); +}; ``` ### Entity class diff --git a/guides/plugins/plugins/framework/data-handling/reading-data.md b/guides/plugins/plugins/framework/data-handling/reading-data.md index e7552be6de..98f560062e 100644 --- a/guides/plugins/plugins/framework/data-handling/reading-data.md +++ b/guides/plugins/plugins/framework/data-handling/reading-data.md @@ -27,19 +27,21 @@ Dealing with the Data Abstraction Layer is done by using the automatically gener The repository's service name follows this pattern: `entity_name.repository` For products this then would be `product.repository`, so let's do this. -```xml -// SwagBasicExample/src/Resources/config/services.xml - - - - - - - - - +```php +// SwagBasicExample/src/Resources/config/services.php +services(); + + $services->set(ReadingData::class) + ->args([service('product.repository')]); +}; ``` And here's the respective class including its constructor: diff --git a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md index b0e5d1e0ab..4ee9982f5e 100644 --- a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md +++ b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md @@ -55,20 +55,24 @@ In order to delete it, we once again need its repository. The name for the entit So let's inject this repository into our class called `ReplacingData`: -```xml -// SwagBasicExample/src/Resources/config/services.xml - - - - - - - - - - +```php +// SwagBasicExample/src/Resources/config/services.php +services(); + + $services->set(ReplacingData::class) + ->args([ + service('product.repository'), + service('product_category.repository'), + ]); +}; ``` Afterwards, you can just use the `delete` method on the repository, just like you did before in the [Writing data](writing-data) guide. diff --git a/guides/plugins/plugins/framework/data-handling/using-database-events.md b/guides/plugins/plugins/framework/data-handling/using-database-events.md index 2c6278da94..853c83283c 100644 --- a/guides/plugins/plugins/framework/data-handling/using-database-events.md +++ b/guides/plugins/plugins/framework/data-handling/using-database-events.md @@ -246,20 +246,19 @@ class ProductSubscriber implements EventSubscriberInterface After creating the event subscriber, you have to register it. If you don't know how that's done, head over to our guide about [Listening to events](../../plugin-fundamentals/listening-to-events). -Here's our `services.xml`: - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - +Here's our `services.php`: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ProductSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` diff --git a/guides/plugins/plugins/framework/data-handling/writing-data.md b/guides/plugins/plugins/framework/data-handling/writing-data.md index 520a8a9916..c8a089bb16 100644 --- a/guides/plugins/plugins/framework/data-handling/writing-data.md +++ b/guides/plugins/plugins/framework/data-handling/writing-data.md @@ -32,20 +32,24 @@ Dealing with the Data Abstraction Layer is done by using the automatically gener The repository's service name follows this pattern: `entity_name.repository` For products this then would be `product.repository`. Additional to that, you're going to need the `tax` repository later for this guide, so let's add this as well already. -```xml -// SwagBasicExample/src/Resources/config/services.xml - - - - - - - - - - +```php +// SwagBasicExample/src/Resources/config/services.php +services(); + + $services->set(WritingData::class) + ->args([ + service('product.repository'), + service('tax.repository'), + ]); +}; ``` And here's the respective class including its constructor: @@ -72,7 +76,7 @@ class WritingData } ``` -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 a constructor parameter. If you want to fetch data for another entity, just switch the service reference in the `services.php` to whatever repository you need, e.g. `order.repository` for orders. ### Creating data diff --git a/guides/plugins/plugins/framework/event/finding-events.md b/guides/plugins/plugins/framework/event/finding-events.md index 421154e622..c10715e1aa 100644 --- a/guides/plugins/plugins/framework/event/finding-events.md +++ b/guides/plugins/plugins/framework/event/finding-events.md @@ -121,23 +121,26 @@ Every service, that wants to fire an event sooner or later, needs access to the Hence, you can have a look at all the service definitions for the [Dependency injection container](../../plugin-fundamentals/dependency-injection) and therefore quickly figure out, which services and classes are having access to the said `event_dispatcher`: -```xml - - - - - - - - - - - +```php +services(); + + $services->set(Service::class) + ->args([ + service('Another/Service'), + service('event_dispatcher'), + ]); +}; ``` -Therefore, you could simply search for occurrences of the `event_dispatcher` in the respective `.xml` files. +Therefore, you could simply search for occurrences of the `event_dispatcher` in the respective service definition files. You can also do this the other way around, by having a look at the service's constructor parameters. diff --git a/guides/plugins/plugins/framework/filesystem/filesystem.md b/guides/plugins/plugins/framework/filesystem/filesystem.md index 5e3028f755..619f9d4573 100644 --- a/guides/plugins/plugins/framework/filesystem/filesystem.md +++ b/guides/plugins/plugins/framework/filesystem/filesystem.md @@ -80,25 +80,29 @@ class ExampleFilesystemService This service makes use of the private und public filesystem. As you already know, this php class has to be registered as a service in the dependency injection container. This is also the place where we define which filesystem will be handed over to the constructor. To make use of the plugin private and public files, the service definition could look like this: -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExampleFilesystemService::class) + ->args([ + service('swag_basic_example.filesystem.public'), + service('swag_basic_example.filesystem.private'), + ]); + // There are also predefined file system services: + // ->args([ + // service('shopware.filesystem.private'), + // service('shopware.filesystem.public'), + // ]) +}; ``` Now, this service can be used to read or write files to the private plugin filesystem or to list all files in the public plugin filesystem. You should visit the [Flysystem API documentation](https://flysystem.thephpleague.com/docs/usage/filesystem-api/) for more information. diff --git a/guides/plugins/plugins/framework/store-api/add-store-api-route.md b/guides/plugins/plugins/framework/store-api/add-store-api-route.md index eb736b4561..764139ec3e 100644 --- a/guides/plugins/plugins/framework/store-api/add-store-api-route.md +++ b/guides/plugins/plugins/framework/store-api/add-store-api-route.md @@ -95,18 +95,20 @@ The `_entity` in the defaults of the `Route` attribute just marks the entity tha ### Register route class -```xml - - - - - - - - - +```php +services(); + + $services->set(ExampleRoute::class) + ->args([service('swag_example.repository')]); +}; ``` ### Route response @@ -336,25 +338,25 @@ Additionally, we also use the `'XmlHttpRequest' => true` config option on the ro ### Register the Controller -```xml - - - - - - - - - - - - - - - - +```php +services(); + + $services->set(ExampleRoute::class) + ->args([service('swag_example.repository')]); + + $services->set(ExampleController::class) + ->args([service(ExampleRoute::class)]) + ->call('setContainer', [service('service_container')]); +}; ``` ### Register Storefront api-route diff --git a/guides/plugins/plugins/framework/store-api/override-existing-route.md b/guides/plugins/plugins/framework/store-api/override-existing-route.md index f3fef7fa48..73d454ac5d 100644 --- a/guides/plugins/plugins/framework/store-api/override-existing-route.md +++ b/guides/plugins/plugins/framework/store-api/override-existing-route.md @@ -72,21 +72,27 @@ As you can see, our decorated route has to extend from the `AbstractExampleRoute Last, we have to register the decorated route to the DI-container. The `ExampleRouteDecorator` has to be registered after the `ExampleRoute` with the attribute `decorated` which points to the `ExampleRoute`. For the second argument we have to use the `ExampleRouteDecorator.inner`. -```xml -// /src/Resources/config/services.xml - - - - - - ... - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + // ... + + $services->set(ExampleRouteDecorator::class) + ->decorate(ExampleRoute::class) + ->public() + ->args([ + service('swag_example.repository'), + service('.inner'), + ]); +}; ``` diff --git a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md b/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md index b50af8a6b8..05089b96bc 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md @@ -18,21 +18,19 @@ Therefore, you can refer to the [Plugin Base Guide](../plugin-base-guide). ## Adding service -For adding a custom service, you need to provide a `services.xml` file in your plugin. -Place a file with name `services.xml` into a directory called `src/Resources/config/`. +For adding a custom service, you need to provide a `services.php` file in your plugin. +Place a file with name `services.php` into a directory called `src/Resources/config/`. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - +```php [PLUGIN_ROOT/src/Resources/config/services.php] + +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - - - +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); +}; ``` ::: @@ -41,24 +39,26 @@ Now you have two possibilities to add a service to your plugin. ### Using autowire and autoconfigure -Set `autowire` and `autoconfigure` to `true` in your `services.xml` file. +Set `autowire` and `autoconfigure` to `true` in your `services.php` file. Symfony will then automatically register your service. Read more about it in the [Symfony docs](https://symfony.com/doc/current/service_container.html#creating-configuring-services-in-the-container). ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - +```php [PLUGIN_ROOT/src/Resources/config/services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services() + ->defaults() + ->autowire() + ->autoconfigure(); - - - - - + $services->load('Swag\\BasicExample\\', '../../') + ->exclude('../../{Resources,Migration,*.php}'); +}; ``` ::: @@ -73,17 +73,17 @@ Use this option if you want to have more control over your service. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - +```php [PLUGIN_ROOT/src/Resources/config/services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - + $services->set(ExampleService::class); +}; ``` ::: @@ -115,10 +115,10 @@ By default, all services in Shopware 6 are marked as _private_. Read more about [private and public services](https://symfony.com/doc/current/service_container.html#public-versus-private-services). ::: -## Alternatives to XML +## Alternatives to PHP configuration -Symfony offers two other file formats to define your services: YAML and PHP. -In Shopware, it is also possible to use one of these. +Symfony supports two other file formats to define your services: YAML and XML. +However, starting with Symfony 7.4, XML service configuration has been deprecated, and it will no longer be supported in Symfony 8.0. Choose the one that suits you best. ## Next steps diff --git a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md index c6b372c612..6c09c597af 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md @@ -13,7 +13,7 @@ Quite often one might want to run any type of code on a regular basis, e.g. to c ## Prerequisites -This guide is built upon our [plugin base guide](../plugin-base-guide), but that one is not mandatory. Knowing how the `services.xml` file in a plugin works is also helpful, which will be taught in our guides about [Dependency Injection](dependency-injection) and [Creating a service](add-custom-service). It is shortly explained here as well though, so no worries! +This guide is built upon our [plugin base guide](../plugin-base-guide), but that one is not mandatory. Knowing how the `services.php` file in a plugin works is also helpful, which will be taught in our guides about [Dependency Injection](dependency-injection) and [Creating a service](add-custom-service). It is shortly explained here as well though, so no worries! ::: info Refer to this video on **[Adding scheduled tasks](https://www.youtube.com/watch?v=88S9P3x6wYE)**. Also available on our free online training ["Shopware 6 Backend Development"](https://academy.shopware.com/courses/shopware-6-backend-development-with-jisse-reitsma). @@ -21,34 +21,40 @@ Refer to this video on **[Adding scheduled tasks](https://www.youtube.com/watch? ## Registering scheduled task in the DI container -A `ScheduledTask` and its respective `ScheduledTaskHandler` are registered in a plugin's `services.xml`. For it to be found by Shopware 6 automatically, you need to place the `services.xml` file in a `Resources/config/` directory, relative to the location of your plugin's base class. The path could look like this: `/src/Resources/config/services.xml`. - -Here's an example `services.xml` containing a new `ScheduledTask` as well as a new `ScheduledTaskHandler`: - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - - - +A `ScheduledTask` and its respective `ScheduledTaskHandler` are registered in a plugin's `services.php`. For it to be found by Shopware 6 automatically, you need to place the `services.php` file in a `Resources/config/` directory, relative to the location of your plugin's base class. The path could look like this: `/src/Resources/config/services.php`. + +Here's an example `services.php` containing a new `ScheduledTask` as well as a new `ScheduledTaskHandler`: + +```php +// /src/Resources/config/services.php +services(); + + $services->set(ExampleTask::class) + ->tag('shopware.scheduled.task'); + + $services->set(ExampleTaskHandler::class) + ->args([ + service('scheduled_task.repository'), + service('logger'), + ]) + ->tag('messenger.message_handler'); +}; ``` Note the tags required for both the task and its respective handler, `shopware.scheduled.task` and `messenger.message_handler`. Your custom task will now be saved into the database once your plugin is activated. ## ScheduledTask and its handler -As you might have noticed, the `services.xml` file tries to find both the task itself as well as the new task handler in a directory called `Service/ScheduledTask`. This naming is up to you, Shopware 6 decided to use this name though. +As you might have noticed, the `services.php` file tries to find both the task itself as well as the new task handler in a directory called `Service/ScheduledTask`. This naming is up to you, Shopware 6 decided to use this name though. Here's the an example `ScheduledTask`: @@ -102,7 +108,7 @@ class ExampleTaskHandler extends ScheduledTaskHandler } ``` -The task handler, `ExampleTaskHandler` as defined previously in your `services.xml`, will be annotated with `AsMessageHandler` handling the `ExampleTask` class. In addition, the `ScheduledTaskHandler` has to extend from the class `Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler`. This also comes with one method that you need to implement first: +The task handler, `ExampleTaskHandler` as defined previously in your `services.php`, will be annotated with `AsMessageHandler` handling the `ExampleTask` class. In addition, the `ScheduledTaskHandler` has to extend from the class `Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler`. This also comes with one method that you need to implement first: * `run`: This method is executed once your scheduled task is executed. Do everything, that your task is supposed to do here. In this example, it will just create a new file. diff --git a/guides/plugins/plugins/plugin-fundamentals/adjusting-service.md b/guides/plugins/plugins/plugin-fundamentals/adjusting-service.md index c7c809b0cc..abd6402944 100644 --- a/guides/plugins/plugins/plugin-fundamentals/adjusting-service.md +++ b/guides/plugins/plugins/plugin-fundamentals/adjusting-service.md @@ -21,26 +21,29 @@ Refer to this video on **[Decorating services](https://www.youtube.com/watch?v=R ## Decorating the service -First of all we have to create a new service for this example which gets decorated in the next step. Then we have to add a new service to our `services.xml` with the attribute `decorates` pointing to our service we want to decorate. Next we have to add our service decorator as argument, but we append an `.inner` to the end of the service to keep the old one as reference. +First of all we have to create a new service for this example which gets decorated in the next step. Then we have to add a new service to our `services.php` with the `decorate` method pointing to our service we want to decorate. The `.inner` reference is used to keep the old one as reference. -Here's our example `services.xml`: +Here's our example `services.php`: -```xml -// /src/Resources/config/services.xml - +```php +// /src/Resources/config/services.php + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - + $services->set(ExampleService::class); - - - - - + $services->set(ExampleServiceDecorator::class) + ->decorate(ExampleService::class) + ->args([service('.inner')]); +}; ``` Now we have to define an abstract class because it's more beautiful and not so strict like interfaces. With an abstract class we can add new functions easier, you can read more about this at the end of this article. The abstract class has to include an abstract function called `getDecorated()` which has the return type of our instance. diff --git a/guides/plugins/plugins/plugin-fundamentals/dependency-injection.md b/guides/plugins/plugins/plugin-fundamentals/dependency-injection.md index dd42a95c54..c9f1ea4559 100644 --- a/guides/plugins/plugins/plugin-fundamentals/dependency-injection.md +++ b/guides/plugins/plugins/plugin-fundamentals/dependency-injection.md @@ -59,7 +59,7 @@ class ExampleService ### Using autowire and autoconfigure -If you previously declared `autowire` and `autoconfigure` in your `services.xml` file, you do not need to do anything else. +If you previously declared `autowire` and `autoconfigure` in your `services.php` file, you do not need to do anything else. The `SystemConfigService` will be injected into the `ExampleService` automatically. ### Explicit declaration @@ -68,19 +68,21 @@ If you declared the service explicitly, you need to add the `SystemConfigService ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - +```php [PLUGIN_ROOT/src/Resources/config/services.php] + +return static function (ContainerConfigurator $configurator): void { + $services = $configurator->services(); - - - - - - + $services->set(ExampleService::class) + ->args([service(SystemConfigService::class)]); +}; ``` ::: diff --git a/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md b/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md index f97e196fd5..a77932e951 100644 --- a/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md +++ b/guides/plugins/plugins/plugin-fundamentals/listening-to-events.md @@ -24,8 +24,8 @@ Also available on our free online training ["Shopware 6 Backend Development"](ht ### Plugin base class -Registering a custom subscriber requires to load a `services.xml` file with your plugin. -This is done by either placing a file with name `services.xml` into a directory called `src/Resources/config/`. +Registering a custom subscriber requires to load a `services.php` file with your plugin. +This is done by either placing a file with name `services.php` into a directory called `src/Resources/config/`. Basically, that's it already if you're familiar with [Symfony subscribers](https://symfony.com/doc/current/event_dispatcher.html#creating-an-event-subscriber). Don't worry, we got you covered here as well. @@ -103,28 +103,27 @@ class MySubscriber implements EventSubscriberInterface } ``` -Unfortunately, your subscriber is not even loaded yet - this will be done in the previously registered `services.xml` file. +Unfortunately, your subscriber is not even loaded yet - this will be done in the previously registered `services.php` file. -### Registering your subscriber via services.xml +### Registering your subscriber via services.php Registering your subscriber to Shopware 6 is also as simple as it is in Symfony. -You're simply registering your \(subscriber\) service by mentioning it in the `services.xml`. +You're simply registering your \(subscriber\) service by mentioning it in the `services.php`. The only difference to a normal service is that you need to add the `kernel.event_subscriber` tag to your subscriber for it to be recognized as such. ```php -// /src/Resources/config/services.xml - - - - - - - - - - +// /src/Resources/config/services.php +services(); + + $services->set(MySubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` That's it, your subscriber service is now automatically loaded at runtime, and it should start listening to the mentioned events to be dispatched. diff --git a/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md b/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md index 75620cdfbb..bb80894ea0 100644 --- a/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md +++ b/guides/plugins/plugins/plugin-fundamentals/use-plugin-configuration.md @@ -68,21 +68,23 @@ Let's get to the important part. Reading the plugin configuration is based on th Inject this service into your subscriber using the [DI container](https://symfony.com/doc/current/service_container.html). -```xml -// /src/Resources/config/services.xml - - - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set(MySubscriber::class) + ->args([service(SystemConfigService::class)]) + ->tag('kernel.event_subscriber'); +}; ``` Note the new `argument` being provided to your subscriber. Now create a new field in your subscriber and pass in the `SystemConfigService`: diff --git a/guides/plugins/plugins/storefront/add-cookie-to-manager.md b/guides/plugins/plugins/storefront/add-cookie-to-manager.md index 08b1dea29f..d08c8d8d14 100644 --- a/guides/plugins/plugins/storefront/add-cookie-to-manager.md +++ b/guides/plugins/plugins/storefront/add-cookie-to-manager.md @@ -29,22 +29,21 @@ It is recommended to use an event listener if you're listening to a single event ### Registering your event listener -Start with creating the `services.xml` and registering your event listener. - -```xml -// /src/Resources/config/services.xml - - - - - - - - - - +Start with creating the `services.php` and registering your event listener. + +```php +// /src/Resources/config/services.php +services(); + + $services->set(CookieListener::class) + ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\Cookie\Event\CookieGroupCollectEvent']); +}; ``` In the next step we'll create the actual listener class. diff --git a/guides/plugins/plugins/storefront/add-custom-controller.md b/guides/plugins/plugins/storefront/add-custom-controller.md index 8b51640df3..8ab7abf5b8 100644 --- a/guides/plugins/plugins/storefront/add-custom-controller.md +++ b/guides/plugins/plugins/storefront/add-custom-controller.md @@ -135,32 +135,32 @@ class ExampleController extends StorefrontController ::: -### Services.xml example +### Services.php example Next, we need to register our controller in the DI-container and make it public. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(ExampleController::class) + ->public() + ->call('setContainer', [service('service_container')]); +}; ``` ::: -Please also note the `call` tag, which is necessary in order to set the DI container to the controller. +Please also note the `call` method, which is necessary in order to set the DI container to the controller. ### Routes.xml example @@ -228,7 +228,7 @@ use Symfony\Component\Routing\Attribute\Route; #[Route(defaults: [PlatformRequest::ATTRIBUTE_ROUTE_SCOPE => [StorefrontRouteScope::ID]])] class ExampleController extends StorefrontController -{ +{ #[Route(path: '/example', name: 'frontend.example.example', methods: ['GET'])] public function showExample(Request $request, SalesChannelContext $context): Response { diff --git a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md b/guides/plugins/plugins/storefront/add-data-to-storefront-page.md index f5dc9011ae..5af32403b8 100644 --- a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md +++ b/guides/plugins/plugins/storefront/add-data-to-storefront-page.md @@ -70,12 +70,10 @@ class AddDataToPage implements EventSubscriberInterface The next thing we need to do is register our subscriber in the DI-Container and tag it as an event subscriber: -```xml -// Resources/config/services.xml - - - - +```php +// Resources/config/services.php +$services->set(\Swag\BasicExample\Service\AddDataToPage::class) + ->tag('kernel.event_subscriber'); ``` ### Adding data to the page @@ -162,7 +160,7 @@ class ProductCountRoute extends AbstractProductCountRoute $productCountResult = $this->productRepository ->aggregate($criteria, $context->getContext()) ->get('productCount'); - + return new ProductCountRouteResponse($productCountResult); } } @@ -170,18 +168,20 @@ class ProductCountRoute extends AbstractProductCountRoute ### Register route class -```xml - - - - - - - - - +```php +services(); + + $services->set(ProductCountRoute::class) + ->args([service('product.repository')]); +}; ``` The routes.xml according to our guide for [adding store-api routes](../framework/store-api/add-store-api-route) should look like this. @@ -274,23 +274,26 @@ This data will then be available via the name `product_count`, but we'll get to Now you only have to adjust your service definition to inject the productCountRoute: -```xml - - - - - - - - - - - - - - +```php +services(); + + $services->set(ProductCountRoute::class) + ->public() + ->args([service('product.repository')]); + + $services->set(AddDataToPage::class) + ->args([service(ProductCountRoute::class)]) + ->tag('kernel.event_subscriber'); +}; ``` ### Displaying the data in the Storefront diff --git a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md index 6a85b7eb90..3542d32b37 100644 --- a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md +++ b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md @@ -54,25 +54,25 @@ As you might have seen, this controller isn't too different from the controller The route attribute has an added `defaults: ['XmlHttpRequest' => true]` to allow XmlHttpRequest, and it returns a `JsonResponse` instead of a normal `Response`. 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 following `services.php` and `routes.xml` are identical as in the before mentioned article, but here they are for reference anyway: ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(ExampleController::class) + ->public() + ->call('setContainer', [service('service_container')]); +}; ``` ```xml [PLUGIN_ROOT/src/Resources/config/routes.xml] diff --git a/guides/plugins/plugins/storefront/add-scss-variables-via-subscriber.md b/guides/plugins/plugins/storefront/add-scss-variables-via-subscriber.md index 541157e21c..80a5b5a9ed 100644 --- a/guides/plugins/plugins/storefront/add-scss-variables-via-subscriber.md +++ b/guides/plugins/plugins/storefront/add-scss-variables-via-subscriber.md @@ -71,21 +71,20 @@ class ThemeVariableSubscriber implements EventSubscriberInterface - + -```xml - - - - - - - - - - +```php +services(); + + $services->set(ThemeVariableSubscriber::class) + ->tag('kernel.event_subscriber'); +}; ``` @@ -188,23 +187,25 @@ class ThemeVariableSubscriber implements EventSubscriberInterface - + -```xml - - - - - - - - - - - - +```php +services(); + + $services->set(ThemeVariableSubscriber::class) + // add argument SystemConfigService + ->args([service(SystemConfigService::class)]) + ->tag('kernel.event_subscriber'); +}; ``` diff --git a/products/extensions/b2b-suite/guides/core/overload-classes.md b/products/extensions/b2b-suite/guides/core/overload-classes.md index 4a8106ccec..a0802e53a6 100644 --- a/products/extensions/b2b-suite/guides/core/overload-classes.md +++ b/products/extensions/b2b-suite/guides/core/overload-classes.md @@ -13,67 +13,84 @@ nav: To add new functionality or overload existing classes to change functionality, the B2B Suite uses the [Dependency Injection](../../../../../guides/plugins/plugins/plugin-fundamentals/dependency-injection) as an extension system instead of events and hooks, which Shopware uses. -### How does a services.xml look like - -In the release package, our service.xml looks like this: - -```xml - - - - Shopware\B2B\Role\Framework\RoleRepository - [...] - - - - - - - [...] - - - [...] - - +### How does a services.php look like + +In the release package, our services.php looks like this: + +```php +// /src/Resources/config/services.php +services(); + $parameters = $configurator->parameters(); + + $parameters->set('b2b_role.repository_class', RoleRepository::class); + + $services->set('b2b_role.repository_abstract') + ->abstract(true) + ->args([ + service('dbal_connection'), + service('b2b_common.repository_dbal_helper'), + ]); + // [...] + + $services->set('b2b_role.repository', '%b2b_role.repository_class%') + ->parent('b2b_role.repository_abstract'); + // [...] +}; ``` For development (GitHub), it looks like this: -```xml - - - - - - - - - - - - - - - - - - - - - - - - - - - +```php +// /src/Resources/config/services.php +services(); + + $services->set('b2b_role.repository', RoleRepository::class) + ->args([ + service('dbal_connection'), + service('b2b_common.repository_dbal_helper'), + ]); + + $services->set('b2b_role.grid_helper', GridHelper::class) + ->args([service('b2b_role.repository')]); + + $services->set('b2b_role.crud_service', RoleCrudService::class) + ->args([ + service('b2b_role.repository'), + service('b2b_role.validation_service'), + ]); + + $services->set('b2b_role.validation_service', RoleValidationService::class) + ->args([ + service('b2b_common.validation_builder'), + service('validator'), + ]); + + $services->set('b2b_role.acl_route_table', AclRouteAclTable::class) + ->tag('b2b_acl.table'); +}; ``` -We generate the new services.xml files for our package automatically. +We generate the new services.php files for our package automatically. ### How do I use it @@ -83,18 +100,23 @@ You only have to change the parameter or overload the service id. Your service file could look like this: -```xml - - - - - - - [...] - - +```php +// /src/Resources/config/services.php +services(); + + $services->set('b2b_role.repository', YourClass::class) + ->parent('b2b_role.repository_abstract') + ->args([service(YourClass::class)]); + // [...] +}; ``` Just define a class with the same service id as our normal class and add our abstract class as the parent. @@ -104,22 +126,22 @@ An example of your class could look like this: ```php myService = array_pop($args); - + + $this->myService = array_pop($args); + parent::__construct(... $args); } - + public function updateRole(RoleEntity $role): RoleEntity { // your stuff diff --git a/products/extensions/b2b-suite/guides/storefront/how-to-extend-the-storefront.md b/products/extensions/b2b-suite/guides/storefront/how-to-extend-the-storefront.md index 08cb7fcaa2..4ec08eaba7 100644 --- a/products/extensions/b2b-suite/guides/storefront/how-to-extend-the-storefront.md +++ b/products/extensions/b2b-suite/guides/storefront/how-to-extend-the-storefront.md @@ -11,19 +11,21 @@ In order to be able to extend the templates of the B2B Suite with another plugin ## Registering a TemplateNamespaceHierarchyBuilder -Register the `TemplateNamespaceHierarchyBuilder` by tagging it in the `services.xml` file of your plugin. - -```xml - - - - - - - - +Register the `TemplateNamespaceHierarchyBuilder` by tagging it in the `services.php` file of your plugin. + +```php +// /src/Resources/config/services.php +services(); + + $services->set(TemplateNamespaceHierarchyBuilder::class) + ->tag('shopware.twig.hierarchy_builder', ['priority' => 750]); +}; ``` The really important part here is the priority. `750` should work fine for most cases, but if you are having problems here, play around with the priority. From 5b0cf0847c2e20c633f694dd1ffe7068602435fc Mon Sep 17 00:00:00 2001 From: umut Date: Mon, 2 Mar 2026 16:38:47 +0100 Subject: [PATCH 2/7] chore: use php configs in router examples --- .../store-api/add-store-api-route.md | 44 +++++++++---------- .../storefront/add-custom-controller.md | 17 ++++--- .../storefront/add-data-to-storefront-page.md | 18 ++++---- .../add-dynamic-content-via-ajax-calls.md | 17 ++++--- 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/guides/plugins/plugins/framework/store-api/add-store-api-route.md b/guides/plugins/plugins/framework/store-api/add-store-api-route.md index 764139ec3e..170718ec1c 100644 --- a/guides/plugins/plugins/framework/store-api/add-store-api-route.md +++ b/guides/plugins/plugins/framework/store-api/add-store-api-route.md @@ -140,18 +140,17 @@ class ExampleRouteResponse extends StoreApiResponse ## Register route -The last thing we need to do now is to tell Shopware how to look for new routes in our plugin. This is done with a `routes.xml` file at `/src/Resources/config/` location. Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. - -```xml -// /src/Resources/config/routes.xml - - - - - +The last thing we need to do now is to tell Shopware how to look for new routes in our plugin. This is done with a `routes.php` file at `/src/Resources/config/` location. Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. + +```php +// /src/Resources/config/routes.php +import('../../Core/**/*Route.php', 'attribute'); +}; ``` ## Check route via Symfony debugger @@ -361,19 +360,18 @@ return static function (ContainerConfigurator $configurator): void { ### Register Storefront api-route -We need to tell Shopware that there is a new API-route for the `storefront` scope by extending the `routes.xml` to also include all Storefront controllers. +We need to tell Shopware that there is a new API-route for the `storefront` scope by extending the `routes.php` to also include all Storefront controllers. -```xml -// /src/Resources/config/routes.xml - - +```php +// /src/Resources/config/routes.php + - - +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; + +return static function (RoutingConfigurator $routes): void { + $routes->import('../../Core/**/*Route.php', 'attribute'); + $routes->import('../../Storefront/**/*Controller.php', 'attribute'); +}; ``` ### Requesting your route from the Storefront diff --git a/guides/plugins/plugins/storefront/add-custom-controller.md b/guides/plugins/plugins/storefront/add-custom-controller.md index 8ab7abf5b8..c7bca9be8b 100644 --- a/guides/plugins/plugins/storefront/add-custom-controller.md +++ b/guides/plugins/plugins/storefront/add-custom-controller.md @@ -170,15 +170,14 @@ Have a look at the official [Symfony documentation](https://symfony.com/doc/curr ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/routes.xml] - - - - - +```php [PLUGIN_ROOT/src/Resources/config/routes.php] +import('../../Storefront/Controller/*Controller.php', 'attribute'); +}; ``` ::: diff --git a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md b/guides/plugins/plugins/storefront/add-data-to-storefront-page.md index 5af32403b8..fc049d1388 100644 --- a/guides/plugins/plugins/storefront/add-data-to-storefront-page.md +++ b/guides/plugins/plugins/storefront/add-data-to-storefront-page.md @@ -184,17 +184,17 @@ return static function (ContainerConfigurator $configurator): void { }; ``` -The routes.xml according to our guide for [adding store-api routes](../framework/store-api/add-store-api-route) should look like this. +The routes.php according to our guide for [adding store-api routes](../framework/store-api/add-store-api-route) should look like this. -```xml - - +```php +// /src/Resources/config/routes.php + - +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; + +return static function (RoutingConfigurator $routes): void { + $routes->import('../../Core/**/*Route.php', 'attribute'); +}; ``` ### ProductCountRouteResponse diff --git a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md index 3542d32b37..d454120361 100644 --- a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md +++ b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md @@ -75,15 +75,14 @@ return static function (ContainerConfigurator $configurator): void { }; ``` -```xml [PLUGIN_ROOT/src/Resources/config/routes.xml] - - - - - +```php [PLUGIN_ROOT/src/Resources/config/routes.php] +import('../../Storefront/Controller/**/*Controller.php', 'attribute'); +}; ``` ::: From 81e8597f97c04a9f81530a72e8d098529d526fca Mon Sep 17 00:00:00 2001 From: umut Date: Tue, 3 Mar 2026 09:38:31 +0100 Subject: [PATCH 3/7] chore: use php configs in partial config file examples and mentions --- concepts/framework/data-abstraction-layer.md | 9 +-- .../configurations/observability/profiling.md | 7 +- guides/hosting/performance/session.md | 7 +- guides/plugins/plugins/bundle.md | 6 +- .../checkout/cart/add-cart-discounts.md | 2 +- .../plugins/framework/caching/index.md | 17 ++-- .../data-handling/add-custom-complex-data.md | 4 +- .../data-handling/entities-via-attributes.md | 9 +-- .../framework/data-handling/reading-data.md | 2 +- .../extension/creating-custom-extension.md | 70 ++++++++-------- .../framework/extension/finding-extensions.md | 30 ++++--- .../framework/flow/add-flow-builder-action.md | 29 ++++--- .../flow/add-flow-builder-trigger.md | 15 ++-- .../framework/rule/add-custom-rules.md | 2 +- .../system-check/add-custom-check.md | 15 ++-- .../plugins/framework/system-check/index.md | 7 +- .../add-custom-commands.md | 14 +--- guides/plugins/plugins/redis.md | 36 ++++----- .../storefront/add-custom-controller.md | 4 +- .../plugins/storefront/add-custom-page.md | 40 ++++++---- .../storefront/add-custom-twig-function.md | 12 ++- .../add-dynamic-content-via-ajax-calls.md | 2 +- .../plugins/storefront/add-translations.md | 10 +-- products/cli/extension-commands/build.md | 4 +- ...ow-to-add-more-fields-to-product-search.md | 12 +-- ...ne-your-custom-Elasticsearch-definition.md | 22 ++--- .../How-to-modify-search-logic.md | 12 +-- .../guides/04-add-new-approval-condition.md | 10 +-- .../development/adding-component.md | 7 +- .../development/extending-migration.md | 7 +- .../development/handler.md | 27 +++---- .../b2b-suite/guides/core/authentication.md | 10 +-- .../b2b-suite/guides/core/entity-acl.md | 80 +++++++++---------- .../b2b-suite/guides/core/rest-api.md | 9 +-- 34 files changed, 270 insertions(+), 279 deletions(-) diff --git a/concepts/framework/data-abstraction-layer.md b/concepts/framework/data-abstraction-layer.md index 2447b4c082..ef21cb43ab 100644 --- a/concepts/framework/data-abstraction-layer.md +++ b/concepts/framework/data-abstraction-layer.md @@ -47,11 +47,10 @@ If you are using [Service autowiring](https://symfony.com/doc/current/service_co Alternatively, configure the `product.repository` service to be injected explicitly: -```html -// src/Resources/config/service.xml - - - +```php +// src/Resources/config/services.php +$services->set(Swag\ExamplePlugin\Service\DalExampleService::class) + ->args([service('product.repository')]); ``` You can read more about dependency injection and service registration in Shopware in the services guides: diff --git a/guides/hosting/configurations/observability/profiling.md b/guides/hosting/configurations/observability/profiling.md index d5ce6761a1..26cbec96bc 100644 --- a/guides/hosting/configurations/observability/profiling.md +++ b/guides/hosting/configurations/observability/profiling.md @@ -70,10 +70,9 @@ class ConsoleProfiler implements ProfilerInterface } ``` -```XML - - - +```php +$services->set(App\Profiler::class) + ->tag('shopware.profiler', ['integration' => 'Console']); ``` The attribute `integration` is used to identify the profiler backend in the configuration. diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index 421083fc88..8ad4b9af47 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -51,10 +51,9 @@ To use one of these handlers, you must create a new service in the dependency in Example service definition: -```xml - - - +```php +$services->set('session.db', Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::class) + ->args([/* ... */]); ``` Example session configuration: diff --git a/guides/plugins/plugins/bundle.md b/guides/plugins/plugins/bundle.md index d1ec4876b2..767a9ffdb8 100644 --- a/guides/plugins/plugins/bundle.md +++ b/guides/plugins/plugins/bundle.md @@ -33,8 +33,8 @@ project-root/ │ │ └── Migration1234567890YourMigration.php │ └── Resources/ │ ├── config/ -│ │ ├── services.xml -│ │ └── routes.xml +│ │ ├── services.php +│ │ └── routes.php │ ├── views/ │ │ └── storefront/ │ │ └── page/ @@ -92,7 +92,7 @@ App\YourBundleName\YourBundleName::class => ['all' => true], ## Adding services, twig templates, routes, theme, etc You can add services, twig templates, routes, etc. to your bundle like you would do in a plugin. -Just create `Resources/config/services.xml` and `Resources/config/routes.xml` files or `Resources/views` for twig templates. +Just create `Resources/config/services.php` and `Resources/config/routes.php` files or `Resources/views` for twig templates. The bundle will be automatically detected and the files will be loaded. To mark your bundle as a theme, it's enough to implement the `Shopware\Core\Framework\ThemeInterface` interface in your bundle class. diff --git a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md index fa178d6693..04b6abedc9 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md @@ -120,4 +120,4 @@ Shopware comes with a called `LineItemRule`, which requires two parameters: After adding the definition to the line item, we have to calculate the current price of the discount. Therefore we can use the `PercentagePriceCalculator` of the core. The last step is to add the discount to the new cart which is provided as `Cart $toCalculate`. -That's it for the main code of our custom `CartProcessor`. Now we only have to register it in our `services.xml` using the tag `shopware.cart.processor` and priority `4500`, which is used to get access to the calculation after the [product processor](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Checkout/DependencyInjection/cart.xml#L223-L231) handled the products. +That's it for the main code of our custom `CartProcessor`. Now we only have to register it in our `services.php` using the tag `shopware.cart.processor` and priority `4500`, which is used to get access to the calculation after the [product processor](https://github.com/shopware/shopware/blob/v6.3.4.1/src/Core/Checkout/DependencyInjection/cart.xml#L223-L231) handled the products. diff --git a/guides/plugins/plugins/framework/caching/index.md b/guides/plugins/plugins/framework/caching/index.md index 9c416fe1d5..668348c97c 100644 --- a/guides/plugins/plugins/framework/caching/index.md +++ b/guides/plugins/plugins/framework/caching/index.md @@ -295,16 +295,13 @@ Therefore, all events it listens to are configured over the service configuratio :::code-group -```xml [PLUGIN_ROOT/src/Core/Framework/DependencyInjection/cache.xml] - - - - - - - - - +```php [PLUGIN_ROOT/src/Core/Framework/DependencyInjection/cache.php] +$services->set(Shopware\Core\Framework\Adapter\Cache\CacheInvalidationSubscriber::class) + ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\Category\Event\CategoryIndexerEvent', 'method' => 'invalidateCategoryRouteByCategoryIds', 'priority' => 2000]) + ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\Category\Event\CategoryIndexerEvent', 'method' => 'invalidateListingRouteByCategoryIds', 'priority' => 2001]) + ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\LandingPage\Event\LandingPageIndexerEvent', 'method' => 'invalidateIndexedLandingPages', 'priority' => 2000]) + // ... +; ``` ::: diff --git a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md index 15cf31b843..28bbb4d3b3 100644 --- a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md +++ b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md @@ -163,9 +163,9 @@ Another thing to note is the `addFlags` call on the `IdField`. Those flags are l If you want to know more about the flags and how to use them, head over to our guide on how to use flags [Using flags](using-flags). -All that's left to do now, is to introduce your `ExampleDefinition` to Shopware by registering your class in your `services.xml` file and by using the `shopware.entity.definition` tag, because Shopware is looking for definitions this way. If your plugin does not have a `services.xml` file yet or you don't know how that's done, head over to our guide about registering a custom service [Add a custom class / service](../../plugin-fundamentals/add-custom-service) or our guide about the [Dependency injection](../../plugin-fundamentals/dependency-injection). +All that's left to do now, is to introduce your `ExampleDefinition` to Shopware by registering your class in your `services.php` file and by using the `shopware.entity.definition` tag, because Shopware is looking for definitions this way. If your plugin does not have a `services.php` file yet or you don't know how that's done, head over to our guide about registering a custom service [Add a custom class / service](../../plugin-fundamentals/add-custom-service) or our guide about the [Dependency injection](../../plugin-fundamentals/dependency-injection). -Here's the `services.xml` as it should look like: +Here's the `services.php` as it should look like: ```php - - +```php +$services->set(Examples\ExampleEntity::class) + ->tag('shopware.entity'); ``` That's it. diff --git a/guides/plugins/plugins/framework/data-handling/reading-data.md b/guides/plugins/plugins/framework/data-handling/reading-data.md index 98f560062e..e315fe8b59 100644 --- a/guides/plugins/plugins/framework/data-handling/reading-data.md +++ b/guides/plugins/plugins/framework/data-handling/reading-data.md @@ -65,7 +65,7 @@ class ReadingData } ``` -So we registered a custom service called `ReadingData` and applied the repository 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 `ReadingData` and applied the repository as a constructor parameter. If you want to fetch data for another entity, just switch the `id` in the `services.php` to whatever repository you need, e.g. `order.repository` for orders. ### Using the repository diff --git a/guides/plugins/plugins/framework/extension/creating-custom-extension.md b/guides/plugins/plugins/framework/extension/creating-custom-extension.md index 22a8804f65..9d8aef0534 100644 --- a/guides/plugins/plugins/framework/extension/creating-custom-extension.md +++ b/guides/plugins/plugins/framework/extension/creating-custom-extension.md @@ -32,14 +32,14 @@ use Shopware\Core\Framework\Log\Package; final class MyCustomExtension extends Extension { public const NAME = 'my-plugin.custom-extension'; - + public function __construct( /** * @public * @description Input data for processing */ public readonly array $inputData, - + /** * @public * @description Context for the operation @@ -83,20 +83,20 @@ use Shopware\Core\System\SalesChannel\SalesChannelContext; final class CustomProductFilterExtension extends Extension { public const NAME = 'my-plugin.product-filter'; - + public function __construct( /** * @public * @description The search criteria for products */ public readonly Criteria $criteria, - + /** * @public * @description The sales channel context */ public readonly SalesChannelContext $context, - + /** * @public * @description Custom filter parameters @@ -132,7 +132,7 @@ class CustomProductService private readonly EntityRepository $productRepository ) { } - + public function filterProducts( Criteria $criteria, SalesChannelContext $context, @@ -143,7 +143,7 @@ class CustomProductService $context, $filterParams ); - + return $this->extensionDispatcher->publish( CustomProductFilterExtension::NAME, $extension, @@ -173,28 +173,28 @@ class CustomProductFilterSubscriber implements EventSubscriberInterface private readonly ProductFilterService $filterService ) { } - + public static function getSubscribedEvents(): array { return [ 'my-plugin.product-filter.pre' => 'onProductFilter', ]; } - + public function onProductFilter(CustomProductFilterExtension $event): void { // Check if we should apply custom filtering if (!$this->shouldApplyCustomFilter($event->filterParams)) { return; } - + // Get filtered product IDs from external API $filteredIds = $this->apiService->getFilteredProductIds( $event->criteria, $event->context, $event->filterParams ); - + if (empty($filteredIds)) { // No products match the filter $event->result = new EntitySearchResult( @@ -208,21 +208,21 @@ class CustomProductFilterSubscriber implements EventSubscriberInterface $event->stopPropagation(); return; } - + // Create new criteria with filtered IDs $newCriteria = clone $event->criteria; $newCriteria->setIds($filteredIds); - + // Apply additional filtering $filteredProducts = $this->filterService->applyBusinessRules( $newCriteria, $event->context ); - + $event->result = $filteredProducts; $event->stopPropagation(); } - + private function shouldApplyCustomFilter(array $filterParams): bool { return isset($filterParams['custom_filter']) && $filterParams['custom_filter'] === true; @@ -232,18 +232,20 @@ class CustomProductFilterSubscriber implements EventSubscriberInterface ### 4. Register Services -```xml - - - - - - - - - - - +```php +// services.php +$services->set(MyPlugin\Service\CustomProductService::class) + ->args([ + service(Shopware\Core\Framework\Extensions\ExtensionDispatcher::class), + service('product.repository'), + ]); + +$services->set(MyPlugin\Subscriber\CustomProductFilterSubscriber::class) + ->args([ + service(MyPlugin\Service\ExternalApiService::class), + service(MyPlugin\Service\ProductFilterService::class), + ]) + ->tag('kernel.event_subscriber'); ``` ## Advanced Extension Patterns @@ -257,7 +259,7 @@ public function onExtension(MyExtension $event): void if (!$this->shouldExecute($event)) { return; } - + $event->result = $this->customImplementation($event); $event->stopPropagation(); } @@ -282,7 +284,7 @@ public function onExtension(MyExtension $event): void 'error' => $e->getMessage(), 'extension' => get_class($event) ]); - + // The extension system will handle the error // and potentially dispatch error events } @@ -308,7 +310,7 @@ private function enrichResult($result, MyExtension $event) 'processedAt' => new \DateTime(), 'context' => $event->context->getSalesChannelId() ])); - + return $result; } ``` @@ -421,7 +423,7 @@ Here's a complete example of a plugin that creates and uses a custom extension p final class ProductRecommendationExtension extends Extension { public const NAME = 'my-plugin.product-recommendation'; - + public function __construct( public readonly ProductEntity $product, public readonly SalesChannelContext $context, @@ -435,7 +437,7 @@ class ProductRecommendationService public function getRecommendations(ProductEntity $product, SalesChannelContext $context): ProductCollection { $extension = new ProductRecommendationExtension($product, $context); - + return $this->extensionDispatcher->publish( ProductRecommendationExtension::NAME, $extension, @@ -456,7 +458,7 @@ class ProductRecommendationSubscriber implements EventSubscriberInterface 'my-plugin.product-recommendation.pre' => 'onGetRecommendations', ]; } - + public function onGetRecommendations(ProductRecommendationExtension $event): void { // Custom AI-powered recommendations @@ -465,7 +467,7 @@ class ProductRecommendationSubscriber implements EventSubscriberInterface $event->context, $event->limit ); - + $event->result = $recommendations; $event->stopPropagation(); } diff --git a/guides/plugins/plugins/framework/extension/finding-extensions.md b/guides/plugins/plugins/framework/extension/finding-extensions.md index 9bff01776a..51b55dbc9e 100644 --- a/guides/plugins/plugins/framework/extension/finding-extensions.md +++ b/guides/plugins/plugins/framework/extension/finding-extensions.md @@ -85,7 +85,7 @@ Extension Points use a `NAME` constant that defines the event name: final class ResolveListingExtension extends Extension { public const NAME = 'listing-loader.resolve'; - + // ... } ``` @@ -95,7 +95,7 @@ final class ResolveListingExtension extends Extension Extension Points are dispatched with lifecycle suffixes: - `{name}.pre` - Before the default implementation -- `{name}.post` - After the default implementation +- `{name}.post` - After the default implementation - `{name}.error` - When an error occurs ## Finding Extension Usage @@ -104,10 +104,9 @@ Extension Points are dispatched with lifecycle suffixes: Services that use Extension Points typically inject the `ExtensionDispatcher`: -```xml - - - +```php +$services->set(Some\Service::class) + ->args([service(Shopware\Core\Framework\Extensions\ExtensionDispatcher::class)]); ``` ### In Constructor Parameters @@ -151,7 +150,7 @@ $result = $this->extensionDispatcher->publish( final class ProductPriceCalculationExtension extends Extension { public const NAME = 'product.calculate-prices'; - + public function __construct( public readonly iterable $products, public readonly SalesChannelContext $context @@ -169,7 +168,7 @@ final class ProductPriceCalculationExtension extends Extension final class ResolveListingExtension extends Extension { public const NAME = 'listing-loader.resolve'; - + public function __construct( public readonly Criteria $criteria, public readonly SalesChannelContext $context @@ -189,7 +188,7 @@ final class ResolveListingExtension extends Extension final class CheckoutPlaceOrderExtension extends Extension { public const NAME = 'checkout.place-order'; - + public function __construct( public readonly Cart $cart, public readonly SalesChannelContext $context @@ -209,7 +208,7 @@ final class CheckoutPlaceOrderExtension extends Extension final class CmsSlotsDataEnrichExtension extends Extension { public const NAME = 'cms.slots.data-enrich'; - + public function __construct( public readonly CmsSlotCollection $slots, public readonly SalesChannelContext $context @@ -239,7 +238,7 @@ class ProductListingSubscriber implements EventSubscriberInterface 'listing-loader.resolve.pre' => 'onResolveListing', ]; } - + public function onResolveListing(ResolveListingExtension $event): void { // Custom logic here @@ -253,10 +252,9 @@ class ProductListingSubscriber implements EventSubscriberInterface Register your subscriber in the service configuration: -```xml - - - +```php +$services->set(MyPlugin\Subscriber\ProductListingSubscriber::class) + ->tag('kernel.event_subscriber'); ``` ## Extension Lifecycle @@ -313,7 +311,7 @@ public function onExtension(SomeExtension $event): void // Another extension already provided a result return; } - + $event->result = $this->myImplementation($event); } ``` diff --git a/guides/plugins/plugins/framework/flow/add-flow-builder-action.md b/guides/plugins/plugins/framework/flow/add-flow-builder-action.md index bfc7f40e32..6a3bee785f 100644 --- a/guides/plugins/plugins/framework/flow/add-flow-builder-action.md +++ b/guides/plugins/plugins/framework/flow/add-flow-builder-action.md @@ -138,14 +138,13 @@ As you can see, several methods are already implemented: - Use `$flow->getStore($key)` if you want to get the data from aware interfaces. E.g: `tag_id` in `TagAware`, `customer_id` from `CustomerAware` and so on. - Use `$flow->getData($key)` if you want to get the data from original events or additional data. E.g: `tag`, `customer`, `contactFormData` and so on. -You also need to register this action in the container as a service. Make sure to define a tag `` at `/src/Resources/config/services.xml`. This tag will ensure that your action is included in the response of the *`/api/_info/flow-actions.json`* API. The priority attribute will determine the order of the action in the API response. - -```XML -// /src/Resources/config/services.xml - - - - +You also need to register this action in the container as a service. Make sure to define a tag `flow.action` with `priority: 600` at `/src/Resources/config/services.php`. This tag will ensure that your action is included in the response of the *`/api/_info/flow-actions.json`* API. The priority attribute will determine the order of the action in the API response. + +```php +// /src/Resources/config/services.php +$services->set(Swag\CreateTagAction\Core\Content\Flow\Dispatching\Action\CreateTagAction::class) + ->args([service('tag.repository')]) + ->tag('flow.action', ['priority' => 600, 'key' => 'action.create.tag']); ``` Great, your own action is created completely. Let's go to the next step. @@ -311,13 +310,13 @@ class BusinessEventCollectorSubscriber implements EventSubscriberInterface } ``` -And don't forget to register your subscriber to the container at `/src/Resources/config/services.xml`. +And don't forget to register your subscriber to the container at `/src/Resources/config/services.php`. -```xml - - - - +```php + +$services->set(Swag\CreateTagAction\Core\Content\Subscriber\BusinessEventCollectorSubscriber::class) + ->args([service(Shopware\Core\Framework\Event\BusinessEventCollector::class)]) + ->tag('kernel.event_subscriber'); ``` - Define the Event snippet @@ -421,7 +420,7 @@ Component.override('sw-flow-sequence-action', { } return this.$super('getActionDescriptions', sequence) }, - + getCreateTagDescription(config) { const tags = config.tags.join(', '); diff --git a/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md b/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md index 4629c278a4..28ec3682ea 100644 --- a/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md +++ b/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md @@ -210,7 +210,7 @@ class CustomerStorer extends FlowStorer private function getCustomer(string $customerId): Customer { // load customer via $customerId - + return $customer; } } @@ -392,14 +392,13 @@ public static function getSubscribedEvents() } ``` -And remember to register your subscriber to the container at `/src/Resources/config/services.xml` +And remember to register your subscriber to the container at `/src/Resources/config/services.php` -```xml -// /src/Resources/config/services.xml - - - - +```php +// /src/Resources/config/services.php +$services->set(Swag\ExamplePlugin\Core\Checkout\Customer\Subscriber\BusinessEventCollectorSubscriber::class) + ->args([service(Shopware\Core\Framework\Event\BusinessEventCollector::class)]) + ->tag('kernel.event_subscriber'); ``` Well done, you have successfully created your own flow trigger. diff --git a/guides/plugins/plugins/framework/rule/add-custom-rules.md b/guides/plugins/plugins/framework/rule/add-custom-rules.md index 0b1516632d..0962b7f1d2 100644 --- a/guides/plugins/plugins/framework/rule/add-custom-rules.md +++ b/guides/plugins/plugins/framework/rule/add-custom-rules.md @@ -106,7 +106,7 @@ As you can see, several methods are already implemented: * `match`: This checks whether the rule applies. Accordingly, a boolean is returned whether the rule applies or not. * `getConstraints`: This method returns an array of the possible fields and its types. You could also return the `NotBlank` class here, to require this field. -After we've created our rule class, we have to register it in our `services.xml` and tag it as `shopware.rule.definition`. +After we've created our rule class, we have to register it in our `services.php` and tag it as `shopware.rule.definition`. Please keep in mind: The variables to be used in the rule have to be 'protected' and not 'private', otherwise they won't work properly. ::: warning diff --git a/guides/plugins/plugins/framework/system-check/add-custom-check.md b/guides/plugins/plugins/framework/system-check/add-custom-check.md index 49ebeab2df..04497e88d1 100644 --- a/guides/plugins/plugins/framework/system-check/add-custom-check.md +++ b/guides/plugins/plugins/framework/system-check/add-custom-check.md @@ -86,13 +86,14 @@ class LocalDiskSpaceCheck extends BaseCheck Finally, you need to register the custom check as a service resource. -```xml - - %shopware.filesystem.public.type% - %shopware.filesystem.public.config.root% - %warning_threshold_in_mb% - - +```php +$services->set(YourNameSpace\LocalDiskSpaceCheck::class) + ->args([ + '%shopware.filesystem.public.type%', + '%shopware.filesystem.public.config.root%', + '%warning_threshold_in_mb%', + ]) + ->tag('shopware.system_check'); ``` ### Trigger the check diff --git a/guides/plugins/plugins/framework/system-check/index.md b/guides/plugins/plugins/framework/system-check/index.md index 5708525f3a..b7e54e2296 100644 --- a/guides/plugins/plugins/framework/system-check/index.md +++ b/guides/plugins/plugins/framework/system-check/index.md @@ -51,10 +51,9 @@ class CustomSystemChecker } ``` -```xml - - - +```php +$services->set(YourNamepace\CustomSystemChecker::class) + ->args([tagged_iterator('shopware.system_check')]); ``` ### Custom triggers diff --git a/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md b/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md index 3679193170..90ecd35a27 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md @@ -9,17 +9,11 @@ nav: Shopware CLI commands are based on [Symfony Console](https://symfony.com/doc/current/console.html). This means that creating custom commands in Shopware plugins follows the standard Symfony approach. -To add a custom command in a Shopware plugin, you must register it as a service in your plugin’s `src/Resources/config/services.xml` and tag it with `console.command`: +To add a custom command in a Shopware plugin, you must register it as a service in your plugin's `src/Resources/config/services.php` and tag it with `console.command`: -```html - - - - - - - - +```php +$services->set(Swag\BasicExample\Command\ExampleCommand::class) + ->tag('console.command'); ``` Commands registered as services in a Shopware plugin are automatically available via `bin/console`. diff --git a/guides/plugins/plugins/redis.md b/guides/plugins/plugins/redis.md index 934a23e638..dbd614110e 100644 --- a/guides/plugins/plugins/redis.md +++ b/guides/plugins/plugins/redis.md @@ -15,16 +15,17 @@ Once you've set up your Redis connections as explained in the [Redis configurat 1. Inject `Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider` and retrieve connections by name: - ```xml - - - %myservice.redis_connection_name% - + ```php + $services->set(MyCustomService::class) + ->args([ + service(Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider::class), + '%myservice.redis_connection_name%', + ]); ``` ```php class MyCustomService - { + { public function __construct ( private RedisConnectionProvider $redisConnectionProvider, string $connectionName, @@ -42,20 +43,18 @@ Once you've set up your Redis connections as explained in the [Redis configurat 2. Use `Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider` as factory to define custom services: - ```xml - - - %myservice.redis_connection_name% - + ```php + $services->set('my.custom.redis_connection', \Redis::class) + ->factory([service(Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider::class), 'getConnection']) + ->args(['%myservice.redis_connection_name%']); - - - + $services->set(MyCustomService::class) + ->args([service('my.custom.redis_connection')]); ``` ```php class MyCustomService - { + { public function __construct ( private object $redisConnection, ) { } @@ -71,10 +70,9 @@ Once you've set up your Redis connections as explained in the [Redis configurat 3. Inject connection directly by name: - ```xml - - - + ```php + $services->set(MyCustomService::class) + ->args([service('shopware.redis.connection.connection_name')]); ``` Be cautious with this approach! If you change the Redis connection names in your configuration, it will cause container build errors. diff --git a/guides/plugins/plugins/storefront/add-custom-controller.md b/guides/plugins/plugins/storefront/add-custom-controller.md index c7bca9be8b..90dc28e556 100644 --- a/guides/plugins/plugins/storefront/add-custom-controller.md +++ b/guides/plugins/plugins/storefront/add-custom-controller.md @@ -162,10 +162,10 @@ return static function (ContainerConfigurator $configurator): void { Please also note the `call` method, which is necessary in order to set the DI container to the controller. -### Routes.xml example +### Routes.php example Once we've registered our new controller, we have to tell Shopware how we want it to search for new routes in our plugin. -This is done with a `routes.xml` file at `/src/Resources/config/` location. +This is done with a `routes.php` file at `/src/Resources/config/` location. Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. ::: code-group diff --git a/guides/plugins/plugins/storefront/add-custom-page.md b/guides/plugins/plugins/storefront/add-custom-page.md index 2c74792bb5..8c2b3b2036 100644 --- a/guides/plugins/plugins/storefront/add-custom-page.md +++ b/guides/plugins/plugins/storefront/add-custom-page.md @@ -148,11 +148,13 @@ Remember to register your new page loader in the DI container: ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +$services->set(ExamplePageLoader::class) + ->public() + ->args([ + service('Shopware\Storefront\Page\GenericPageLoader'), + service('event_dispatcher'), + ]); ``` ::: @@ -197,19 +199,29 @@ class ExampleController extends StorefrontController Note, that we've added the page to the template variables. -#### Adjusting the services.xml +#### Adjusting the services.php -In addition, it is necessary to pass the argument with the ID of the `ExamplePageLoader` class to the [configuration](add-custom-controller#services-xml-example) of the controller service in the `services.xml`. +In addition, it is necessary to pass the argument with the ID of the `ExamplePageLoader` class to the [configuration](add-custom-controller#services-xml-example) of the controller service in the `services.php`. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +services(); + + $services->set(ExampleController::class) + ->public() + ->args([service(ExamplePageLoader::class)]) + ->call('setContainer', [service('service_container')]); +}; ``` ::: diff --git a/guides/plugins/plugins/storefront/add-custom-twig-function.md b/guides/plugins/plugins/storefront/add-custom-twig-function.md index 1875552df1..5505db59ee 100644 --- a/guides/plugins/plugins/storefront/add-custom-twig-function.md +++ b/guides/plugins/plugins/storefront/add-custom-twig-function.md @@ -65,16 +65,14 @@ class SwagCreateMd5Hash extends AbstractExtension ::: -Of course, you can do everything in the `createMd5Hash` function that PHP can do, but the `service.xml` handles registration of the service in the DI container. +Of course, you can do everything in the `createMd5Hash` function that PHP can do, but the `services.php` handles registration of the service in the DI container. ::: code-group -```xml [PLUGIN_ROOT/src/Resources/config/services.xml] - - - - - +```php [PLUGIN_ROOT/src/Resources/config/services.php] +$services->set(SwagCreateMd5Hash::class) + ->public() + ->tag('twig.extension'); // Required ``` Once done, you can access this `TwigFunction` within your plugin. diff --git a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md index d454120361..fac666c864 100644 --- a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md +++ b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md @@ -54,7 +54,7 @@ As you might have seen, this controller isn't too different from the controller The route attribute has an added `defaults: ['XmlHttpRequest' => true]` to allow XmlHttpRequest, and it returns a `JsonResponse` instead of a normal `Response`. 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.php` and `routes.xml` are identical as in the before mentioned article, but here they are for reference anyway: +The following `services.php` and `routes.php` are identical as in the before mentioned article, but here they are for reference anyway: ::: code-group diff --git a/guides/plugins/plugins/storefront/add-translations.md b/guides/plugins/plugins/storefront/add-translations.md index a59a5a1d0e..4a74dcd900 100644 --- a/guides/plugins/plugins/storefront/add-translations.md +++ b/guides/plugins/plugins/storefront/add-translations.md @@ -26,7 +26,7 @@ You can also use subdirectories if you prefer, although we recommend keeping a f Use `..json` as the naming pattern for the file. The domain can be freely defined (we recommend your extension name in kebab case), while the locale **must** map to the ISO string of the supported locale in this snippet file — for example: `my-app.de.json`. -Locales should follow the ISO string of the supported language, such as `de`, `en`, or `es-AR`. +Locales should follow the ISO string of the supported language, such as `de`, `en`, or `es-AR`. This format follows [IETF BCP 47](https://datatracker.ietf.org/doc/html/bcp47), restricted to [ISO 639-1 (2-letter) language codes](https://en.wikipedia.org/wiki/ISO_639-1) as used by [Symfony](https://symfony.com/doc/current/reference/constraints/Locale.html), but with dashes (`-`) instead of underscores (`_`). For more information on selecting proper locales, see our documentation on [Fallback language selection](../../../../concepts/translations/fallback-language-selection.md). @@ -114,10 +114,10 @@ If we need to use a snippet elsewhere in PHP, we can use [Dependency Injection](../plugin-fundamentals/dependency-injection) to inject the `translator` service, which implements Symfony's `Symfony\Contracts\Translation\TranslatorInterface`: -```xml - - - +```php +$services->set(Swag\Example\Service\SwagService::class) + ->public() + ->args([service('translator')]); ``` ```php diff --git a/products/cli/extension-commands/build.md b/products/cli/extension-commands/build.md index 457f2eb30f..354d60b0d5 100644 --- a/products/cli/extension-commands/build.md +++ b/products/cli/extension-commands/build.md @@ -150,7 +150,7 @@ build: - ``` -For example, to exclude the `src/Resources/config/services.xml` file from checksum calculation: +For example, to exclude the `src/Resources/config/services.php` file from checksum calculation: ```yaml # .shopware-extension.yml @@ -158,7 +158,7 @@ build: zip: checksum: ignore: - - src/Resources/config/services.xml + - src/Resources/config/services.php ``` To verify the checksum of installed extensions, you can use the [FroshTools](https://github.com/FriendsOfShopware/FroshTools#froshextensionchecksumcheck---check-extension-file-integrity) plugin which provides a checksum verification feature for all extensions. diff --git a/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md b/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md index a6101e52e9..522cbb8bd3 100644 --- a/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md +++ b/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md @@ -13,11 +13,13 @@ In this example, we create a field called `productNumberPrefix` to make it searc **1. Decorate the ElasticsearchDefinition** -```xml - - - - +```php +$services->set(YourPluginNameSpace\ElasticsearchProductDefinitionDecorator::class) + ->decorate(Shopware\Elasticsearch\Product\ElasticsearchProductDefinition::class) + ->args([ + service('.inner'), + service(Shopware\Commercial\AdvancedSearch\Domain\Search\SearchLogic::class), + ]); ``` ```php diff --git a/products/extensions/advanced-search/How-to-define-your-custom-Elasticsearch-definition.md b/products/extensions/advanced-search/How-to-define-your-custom-Elasticsearch-definition.md index b67c62647c..079c02c038 100644 --- a/products/extensions/advanced-search/How-to-define-your-custom-Elasticsearch-definition.md +++ b/products/extensions/advanced-search/How-to-define-your-custom-Elasticsearch-definition.md @@ -152,14 +152,16 @@ SQL; And register it in the container with tag `shopware.es.definition` and `advanced_search.supported_definition` -```xml -# YourPluginNameSpace should be changed to your respectively ElasticsearchDefinition and Definition classes - - - - - - - - +```php +// YourPluginNameSpace should be changed to your respectively ElasticsearchDefinition and Definition classes +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; + +$services->set(YourPluginNameSpace\YourCustomElasticsearchDefinition::class) + ->args([ + service(YourPluginNameSpace\YourCustomDefinition::class), + service('Doctrine\DBAL\Connection'), + service(Shopware\Commercial\AdvancedSearch\Domain\Search\SearchLogic::class), + ]) + ->tag('shopware.es.definition') + ->tag('advanced_search.supported_definition'); ``` diff --git a/products/extensions/advanced-search/How-to-modify-search-logic.md b/products/extensions/advanced-search/How-to-modify-search-logic.md index 366eab766c..24767bc80d 100644 --- a/products/extensions/advanced-search/How-to-modify-search-logic.md +++ b/products/extensions/advanced-search/How-to-modify-search-logic.md @@ -19,11 +19,13 @@ This class is the central place to build the Elasticsearch query: To modify the search logic, you can decorate the search logic class and add your own logic into it: -```xml - - - - +```php +$services->set(YourPluginNameSpace\Domain\Search\SearchLogicDecorator::class) + ->decorate(Shopware\Commercial\AdvancedSearch\Domain\Search\SearchLogic::class) + ->args([ + service('.inner'), + service(Shopware\Commercial\AdvancedSearch\Domain\Configuration\ConfigurationLoader::class), + ]); ``` ```php diff --git a/products/extensions/b2b-components/order-approval/guides/04-add-new-approval-condition.md b/products/extensions/b2b-components/order-approval/guides/04-add-new-approval-condition.md index 4471a1411a..7813915ad1 100644 --- a/products/extensions/b2b-components/order-approval/guides/04-add-new-approval-condition.md +++ b/products/extensions/b2b-components/order-approval/guides/04-add-new-approval-condition.md @@ -74,12 +74,12 @@ class CartAmountRule extends Rule } ``` -Then, we have to register it in our `services.xml` and tag it as `shopware.approval_rule.definition` +Then, we have to register it in our `services.php` and tag it as `shopware.approval_rule.definition` -```xml - - - +```php +$services->set(YourPluginNameSpace\CartAmountRule::class) + ->public() + ->tag('shopware.approval_rule.definition'); ``` ## App diff --git a/products/extensions/b2b-suite-migration/development/adding-component.md b/products/extensions/b2b-suite-migration/development/adding-component.md index 7d437c144e..c445e7d16f 100644 --- a/products/extensions/b2b-suite-migration/development/adding-component.md +++ b/products/extensions/b2b-suite-migration/development/adding-component.md @@ -17,10 +17,9 @@ This section guides developers on adding a new component to the migration proces - Tag the class with `b2b.migration.configurator`. **Example**: - ```XML - - - + ```php + $services->set(Shopware\Commercial\B2B\B2BSuiteMigration\Components\EmployeeManagement\EmployeeManagementMigrationConfigurator::class) + ->tag('b2b.migration.configurator', ['priority' => 9000]); ``` ```PHP diff --git a/products/extensions/b2b-suite-migration/development/extending-migration.md b/products/extensions/b2b-suite-migration/development/extending-migration.md index 772974518b..3b8e14d007 100644 --- a/products/extensions/b2b-suite-migration/development/extending-migration.md +++ b/products/extensions/b2b-suite-migration/development/extending-migration.md @@ -18,10 +18,9 @@ This section explains how to add new fields to an existing entity or introduce n **Example**: - ```XML - - - + ```php + $services->set(MigrationExtension\B2BMigration\B2BExtensionMigrationConfigurator::class) + ->tag('b2b.migration.configurator.extension'); ``` ```PHP diff --git a/products/extensions/b2b-suite-migration/development/handler.md b/products/extensions/b2b-suite-migration/development/handler.md index a4ae6c15f3..ea96324741 100644 --- a/products/extensions/b2b-suite-migration/development/handler.md +++ b/products/extensions/b2b-suite-migration/development/handler.md @@ -53,7 +53,7 @@ Handlers allow custom logic to transform data before mapping it to the target fi currency_factor auth_id.b2b_store_front_auth.customer_id.customer.sales_channel_id.sales_channel.language_id - + state_id expiration_date @@ -76,15 +76,14 @@ Handlers allow custom logic to transform data before mapping it to the target fi To use a handler, implement a PHP class (e.g., `RolePermissionsTransformer`) that extends `Shopware\Commercial\B2B\B2BSuiteMigration\Core\Domain\DataTransformer\AbstractFieldTransformer` and tag it with `b2b.migration.transformer` in your service configuration. -```XML - - - - - +```php +$services->set(Shopware\Commercial\B2B\B2BSuiteMigration\Components\QuoteManagement\DataTransformer\QuoteComment\StateTransformer::class) + ->lazy() + ->args([service(Shopware\Core\Framework\Extensions\ExtensionDispatcher::class)]) + ->tag('b2b.migration.transformer'); ``` -The best practice is to mark this service as `lazy="true"` to improve performance by loading it only when needed. +The best practice is to mark this service as `lazy` to improve performance by loading it only when needed. ## Handler Implementation @@ -134,7 +133,7 @@ protected function requiredSourceFields(): array ```XML ``` - + ```PHP protected function requiredSourceFields(): array { @@ -148,11 +147,11 @@ protected function requiredSourceFields(): array foo bar - + permissions ``` - + ```PHP protected function requiredSourceFields(): array { @@ -180,7 +179,7 @@ protected function _transform( - **Return Value**: - For a single target field: Return a single value (e.g., string, integer, or JSON-encoded string). - For multiple target fields: Return an associative array where keys are target field names and values are the corresponding transformed values. - + #### Examples **_Example 1: Single Source to Single Target_** @@ -226,7 +225,7 @@ Transform multiple source fields to multiple target fields, such as generating a list_id mode - + order_id order_version_id @@ -241,7 +240,7 @@ public function transform(Field $field, array $sourceRecord): mixed if (!isset($field->getSourceElements()['list_id']) || !isset($field->getSourceElements()['mode'])) { // Handle missing required source fields } - + $listId = $sourceRecord['list_id']; $mode = $sourceRecord['mode']; // Perform transformation logic based on listId and mode diff --git a/products/extensions/b2b-suite/guides/core/authentication.md b/products/extensions/b2b-suite/guides/core/authentication.md index c82803a9bc..b1149b053b 100644 --- a/products/extensions/b2b-suite/guides/core/authentication.md +++ b/products/extensions/b2b-suite/guides/core/authentication.md @@ -220,12 +220,10 @@ context owner ids. Notice that the interface is designed to be chained to create Finally, you register your authentication provider (in our case a repository) as a tagged service through the DIC. -```xml - - [...] - - - +```php +$services->set('b2b_my.contact_authentication_identity_loader', Shopware\B2B\My\AuthenticationIdentityLoader::class) + // [...] + ->tag('b2b_front_auth.authentication_repository'); ``` ## Sales representative diff --git a/products/extensions/b2b-suite/guides/core/entity-acl.md b/products/extensions/b2b-suite/guides/core/entity-acl.md index 5f2bbad1e4..d6d140b9da 100644 --- a/products/extensions/b2b-suite/guides/core/entity-acl.md +++ b/products/extensions/b2b-suite/guides/core/entity-acl.md @@ -40,10 +40,10 @@ The ACL is represented as M:N relation tables in the database and always looks l ```sql CREATE TABLE `b2b_acl_*` ( `id` INT(11) NOT NULL AUTO_INCREMENT, - `entity_id` INT(11) NOT NULL, + `entity_id` INT(11) NOT NULL, `referenced_entity_id` INT(11) NOT NULL, `grantable` TINYINT(4) NOT NULL DEFAULT '0', - + [...] ); ``` @@ -88,16 +88,16 @@ class AclRepository * @throws AclUnsupportedContextException */ public function allow($context, IdValue $subjectId, bool $grantable = false): void - { - [...] + { + [...] } /** * @throws AclUnsupportedContextException */ - public function allowAll($context, array $subjectIds, bool $grantable = false): void - { - [...] + public function allowAll($context, array $subjectIds, bool $grantable = false): void + { + [...] } /** @@ -119,50 +119,50 @@ class AclRepository /** * @throws AclUnsupportedContextException */ - public function isAllowed($context, IdValue $subjectId): bool - { - [...] + public function isAllowed($context, IdValue $subjectId): bool + { + [...] } /** * @throws AclUnsupportedContextException */ - public function isGrantable($context, IdValue $subjectId): bool - { - [...] + public function isGrantable($context, IdValue $subjectId): bool + { + [...] } /** * @throws AclUnsupportedContextException * @return IdValue[] */ - public function getAllAllowedIds($context): array - { - [...] + public function getAllAllowedIds($context): array + { + [...] } /** * @throws AclUnsupportedContextException */ - public function fetchAllGrantableIds($context): array + public function fetchAllGrantableIds($context): array { - [...] + [...] } /** * @throws AclUnsupportedContextException */ - public function fetchAllDirectlyIds($context): array - { - [...] + public function fetchAllDirectlyIds($context): array + { + [...] } /** * @throws AclUnsupportedContextException */ - public function getUnionizedSqlQuery($context): AclQuery - { - [...] + public function getUnionizedSqlQuery($context): AclQuery + { + [...] } } ``` @@ -201,7 +201,7 @@ $contactRepository = $this->container->get('b2b_contact.repository'); $contact = $contactRepository->fetchOneById(1); $aclAddressRepository->allow( - $contact, // the contact + $contact, // the contact 22, // the id of the address true // whether the contact may grant access to other contacts ); @@ -211,7 +211,7 @@ We can then deny the access just by this: ```php $aclAdressRepository->deny( - $contact, // the contact + $contact, // the contact 22, // the id of the address ); ``` @@ -220,7 +220,7 @@ or just set it not grantable, by ```php $aclAdressRepository->allow( - $contact, // the contact + $contact, // the contact 22, // the id of the address false // whether the contact may grant access to other contacts ); @@ -232,7 +232,7 @@ If you want to know whether a certain contact can access an entity, you can call ```php $aclAdressRepository->isAllowed( - $contact, // the contact + $contact, // the contact 22, // the id of the address ); ``` @@ -241,7 +241,7 @@ Or you just want to check whether an entity can be granted by a contact. ```php $aclAdressRepository->isGrantable( - $contact, // the contact + $contact, // the contact 22, // the id of the address ); ``` @@ -343,19 +343,17 @@ AclDdlService::create()->createTable(new AddressContactTable()); Now the table exists, but we must still make the table definition accessible through the DIC, so the ACL component can set up appropriate repositories. This is achieved through a tag in the service definition: -```xml - - - +```php +$services->set('b2b_address.contact_acl_table', Shopware\B2B\Address\Framework\AddressContactAclTable::class) + ->tag('b2b_acl.table'); ``` -Finally, we need to register the service in the DIC. This is done by this XML snippet: +Finally, we need to register the service in the DIC. This is done by this PHP snippet: -```xml - - - s_user_addresses - +```php +$services->set('b2b_address.acl_repository', Shopware\B2B\Acl\Framework\AclRepository::class) + ->factory([service('b2b_acl.repository_factory'), 'createRepository']) + ->args(['s_user_addresses']); ``` There we are; the addresses are ACL-ified entities. @@ -385,12 +383,12 @@ class MyContextResolver extends AclContextResolver public function extractId($context): int { - // your implementation here + // your implementation here } public function isMainContext(): bool { - // your implementation here + // your implementation here } } ``` diff --git a/products/extensions/b2b-suite/guides/core/rest-api.md b/products/extensions/b2b-suite/guides/core/rest-api.md index 9b6e7747c4..4022360fe9 100644 --- a/products/extensions/b2b-suite/guides/core/rest-api.md +++ b/products/extensions/b2b-suite/guides/core/rest-api.md @@ -74,12 +74,11 @@ class MyApiRouteProvider implements RouteProvider Now the route provider and the controller are registered to the DIC. -```xml - +```php +$services->set('my.controller', My\Namespace\MyApiController::class); - - - +$services->set('my.api_route_provider', My\Namespace\DependencyInjection\MyApiRouteProvider::class) + ->tag('b2b_common.rest_route_provider'); ``` Notice that the route provider is tagged as a `b2b_common.rest_route_provider`. From 3abd5a571e4413268f13c6f2440ebeec0f6de0cc Mon Sep 17 00:00:00 2001 From: umut Date: Tue, 3 Mar 2026 10:22:17 +0100 Subject: [PATCH 4/7] chore: use xml in core related examples --- .../plugins/framework/caching/index.md | 17 ++++++++------ .../custom-field/add-custom-field.md | 22 +++++++++---------- .../fetching-data-from-entity-selection.md | 18 +++++++-------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/guides/plugins/plugins/framework/caching/index.md b/guides/plugins/plugins/framework/caching/index.md index 668348c97c..9c416fe1d5 100644 --- a/guides/plugins/plugins/framework/caching/index.md +++ b/guides/plugins/plugins/framework/caching/index.md @@ -295,13 +295,16 @@ Therefore, all events it listens to are configured over the service configuratio :::code-group -```php [PLUGIN_ROOT/src/Core/Framework/DependencyInjection/cache.php] -$services->set(Shopware\Core\Framework\Adapter\Cache\CacheInvalidationSubscriber::class) - ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\Category\Event\CategoryIndexerEvent', 'method' => 'invalidateCategoryRouteByCategoryIds', 'priority' => 2000]) - ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\Category\Event\CategoryIndexerEvent', 'method' => 'invalidateListingRouteByCategoryIds', 'priority' => 2001]) - ->tag('kernel.event_listener', ['event' => 'Shopware\Core\Content\LandingPage\Event\LandingPageIndexerEvent', 'method' => 'invalidateIndexedLandingPages', 'priority' => 2000]) - // ... -; +```xml [PLUGIN_ROOT/src/Core/Framework/DependencyInjection/cache.xml] + + + + + + + + + ``` ::: diff --git a/guides/plugins/plugins/framework/custom-field/add-custom-field.md b/guides/plugins/plugins/framework/custom-field/add-custom-field.md index 17d79ed13b..1ffcfaf36c 100644 --- a/guides/plugins/plugins/framework/custom-field/add-custom-field.md +++ b/guides/plugins/plugins/framework/custom-field/add-custom-field.md @@ -44,7 +44,7 @@ Also, you may want to add translatable custom fields, which is also covered in v Let's assume you already got a working and running entity definition. If you want to support custom fields with your custom entity, you may add the `EntityCustomFieldsTrait` to your entity class, so the methods `getCustomFields()` and `setCustomFields()` can be used. -```php +```PHP // /src/Core/Content/Example/ExampleEntity.php use Shopware\Core\Framework\DataAbstractionLayer\Entity; use Shopware\Core\Framework\DataAbstractionLayer\EntityCustomFieldsTrait; @@ -65,7 +65,7 @@ class ExampleEntity extends Entity Now follows the important part. For this to work, you have to add the Data Abstraction Layer \(DAL\) field `CustomFields` to your entity definition. -```php +```PHP // /src/Core/Content/Example/ExampleDefinition.php use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; @@ -97,7 +97,7 @@ Once again, this example is built upon the [Add custom complex data](../data-han If you want to support custom fields now, you have to add a new column `custom_fields` of type `JSON` to your migration. -```php +```PHP // /src/Migration/Migration1611664789Example.php public function update(Connection $connection): void { @@ -128,7 +128,7 @@ Note the new `custom_fields` column here. It has to be a JSON field and should d Make sure to understand entity translations in general first, which is explained here [Add data translations](../data-handling/add-data-translations). If you want your custom fields to be translatable, you can simply work with a `TranslatedField` here as well. -```php +```PHP // /src/Core/Content/Example/ExampleDefinition.php use Shopware\Core\Framework\DataAbstractionLayer\Field\TranslatedField; @@ -156,7 +156,7 @@ Just add the `TranslatedField` and apply `customFields` as a parameter. In your translated entity definition, you then add the `CustomFields` field instead. -```php +```PHP // /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationDefinition.php use Shopware\Core\Framework\DataAbstractionLayer\Field\CustomFields; @@ -190,7 +190,7 @@ So let's assume you've got your own `example` entity up and running, and now you In that case, you can use your entities' repository and start creating or updating entities with custom fields. If you don't understand what's going on here, head over to our guide about [Writing data](../data-handling/writing-data) first. -```php +```PHP $this->swagExampleRepository->upsert([[ 'id' => '', 'customFields' => ['swag_example_size' => 15] @@ -201,7 +201,7 @@ This will execute perfectly fine, and you just saved a custom field with name `s As already mentioned, you do not have to define a custom field first before saving it. That's because there is no validation happening here yet, you can write whatever valid JSON you want to that column, so the following example would also execute without any issues: -```php +```PHP $this->swagExampleRepository->upsert([[ 'id' => '', 'customFields' => [ 'foo' => 'bar', 'baz' => [] ] @@ -216,7 +216,7 @@ So now you've already filled the custom fields of one of your entity instances v Only if you want your custom field to show up in the Administration and to be editable in there, you have to define the custom fields first in a custom field set. For this you have to use the custom fieldset repository, which can be retrieved from the dependency injection container via the `custom_field_set.repository` key and is used like any other repository. -```php +```PHP // /src/Resources/config/services.php customFieldSetRepository->searchIds((new Criteria())->addFilter(new EqualsFilter('name', 'swag_example_set')), $context)->firstId(); $this->customFieldSetRepository->delete([['id' => $setId]], $context); ``` @@ -316,7 +316,7 @@ UPDATE swag_example SET custom_fields = JSON_REMOVE(custom_fields, '$.swag_examp If you have a table with a lot of data, like orders or products, you should not approach it carelessly to avoid overwhelming the database with too many changes at once. This can look like this instead: -```php +```PHP $updateLimit = 1000; do { diff --git a/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md b/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md index c139a5dc42..05ec088e6f 100644 --- a/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md +++ b/guides/plugins/plugins/framework/custom-field/fetching-data-from-entity-selection.md @@ -25,7 +25,7 @@ To resolve the `id` and getting access to the product we have linked here, we ca Lets create a `ProductSubscriber` first which will listen to the `ProductEvents::PRODUCT_LOADED_EVENT`. -```php +```PHP // /src/Subscriber/ProductSubscriber.php /src/Resources/config/services.php /src/Subscriber/ProductSubscriber.php getEntities() as $productEntity) { $customFields = $productEntity->getCustomFields(); @@ -117,7 +117,7 @@ But, how we can load the linked product by its `id` if the custom field was set? First we update the `services.php` and inject the product repository. -```php +```PHP // /src/Resources/config/services.php /src/Subscriber/ProductSubscriber.php productRepository = $productRepository; } @@ -167,7 +167,7 @@ As you can see, the product repository was injected and is now available to the Let's have a look at the final implementation of the subscriber. -```php +```PHP // /src/Subscriber/ProductSubscriber.php productRepository = $productRepository; } From 5daa80f5f26f2fe6951ceb07af978ee330e24a39 Mon Sep 17 00:00:00 2001 From: umut Date: Tue, 3 Mar 2026 10:48:38 +0100 Subject: [PATCH 5/7] fix: cs - use capitalized file extension in examples --- concepts/framework/data-abstraction-layer.md | 4 +- .../configurations/observability/profiling.md | 6 +-- guides/hosting/performance/session.md | 4 +- guides/plugins/plugins/bundle.md | 12 +++--- .../checkout/cart/add-cart-discounts.md | 2 +- .../plugins/checkout/cart/add-cart-items.md | 10 ++--- .../checkout/cart/add-cart-validator.md | 8 ++-- .../checkout/cart/change-price-of-item.md | 6 +-- .../cart/customize-price-calculation.md | 4 +- .../plugins/checkout/cart/tax-provider.md | 8 ++-- .../document/add-custom-document-type.md | 2 +- .../content/cms/add-data-to-cms-elements.md | 2 +- .../media/add-custom-file-extension.md | 6 +-- ...-media-files-referenced-in-your-plugins.md | 6 +-- .../plugins/content/seo/add-custom-seo-url.md | 22 +++++------ .../plugins/content/seo/extend-robots-txt.md | 6 +-- .../sitemap/add-custom-sitemap-entries.md | 4 +- .../content/sitemap/modify-sitemap-entries.md | 8 ++-- .../implementing-your-own-stock-storage.md | 4 +- ...stock-information-from-different-source.md | 10 ++--- ...oduct-entity-extension-to-elasticsearch.md | 10 ++--- .../add-complex-data-to-existing-entities.md | 22 +++++------ .../data-handling/add-custom-complex-data.md | 16 ++++---- .../data-handling/add-data-indexer.md | 10 ++--- .../data-handling/add-data-translations.md | 14 +++---- .../data-handling/entities-via-attributes.md | 26 ++++++------- .../framework/data-handling/reading-data.md | 38 +++++++++---------- .../replacing-associated-data.md | 10 ++--- .../data-handling/using-database-events.md | 8 ++-- .../framework/data-handling/writing-data.md | 24 ++++++------ .../plugins/framework/event/finding-events.md | 16 ++++---- .../extension/creating-custom-extension.md | 20 +++++----- .../framework/extension/finding-extensions.md | 38 +++++++++---------- .../framework/filesystem/filesystem.md | 4 +- .../framework/flow/add-flow-builder-action.md | 20 +++++----- .../flow/add-flow-builder-trigger.md | 22 +++++------ .../framework/rule/add-custom-rules.md | 8 ++-- .../store-api/add-store-api-route.md | 28 +++++++------- .../store-api/override-existing-route.md | 4 +- .../system-check/add-custom-check.md | 6 +-- .../plugins/framework/system-check/index.md | 6 +-- .../add-custom-commands.md | 2 +- .../plugin-fundamentals/add-scheduled-task.md | 6 +-- .../plugin-fundamentals/adjusting-service.md | 12 +++--- .../listening-to-events.md | 6 +-- .../use-plugin-configuration.md | 30 +++++++-------- .../storefront/add-cookie-to-manager.md | 4 +- .../storefront/add-custom-controller.md | 2 +- .../storefront/add-data-to-storefront-page.md | 18 ++++----- .../add-scss-variables-via-subscriber.md | 14 +++---- .../plugins/storefront/add-translations.md | 10 ++--- ...ow-to-add-more-fields-to-product-search.md | 10 ++--- ...ne-your-custom-Elasticsearch-definition.md | 4 +- .../How-to-modify-search-logic.md | 4 +- .../guides/04-add-new-approval-condition.md | 4 +- .../development/handler.md | 2 +- .../b2b-suite/guides/core/authentication.md | 26 ++++++------- .../b2b-suite/guides/core/entity-acl.md | 28 +++++++------- .../b2b-suite/guides/core/overload-classes.md | 8 ++-- .../b2b-suite/guides/core/rest-api.md | 10 ++--- .../how-to-extend-the-storefront.md | 4 +- 61 files changed, 344 insertions(+), 344 deletions(-) diff --git a/concepts/framework/data-abstraction-layer.md b/concepts/framework/data-abstraction-layer.md index ef21cb43ab..69533f588a 100644 --- a/concepts/framework/data-abstraction-layer.md +++ b/concepts/framework/data-abstraction-layer.md @@ -35,7 +35,7 @@ This is the recommended way for developers to interface with the DAL or the data Before using the repositories, you will need to get them from the [Dependency Injection Container (DIC)](../../guides/plugins/plugins/plugin-fundamentals/dependency-injection). This is done with [Constructor injection](https://symfony.com/doc/current/service_container/injection_types.html#constructor-injection), so you will need to extend your services constructor by expecting an EntityRepository: -```php +```PHP // /src/Service/DalExampleService.php public function __construct (EntityRepository $productRepository) { @@ -47,7 +47,7 @@ If you are using [Service autowiring](https://symfony.com/doc/current/service_co Alternatively, configure the `product.repository` service to be injected explicitly: -```php +```PHP // src/Resources/config/services.php $services->set(Swag\ExamplePlugin\Service\DalExampleService::class) ->args([service('product.repository')]); diff --git a/guides/hosting/configurations/observability/profiling.md b/guides/hosting/configurations/observability/profiling.md index 26cbec96bc..b27cdf947a 100644 --- a/guides/hosting/configurations/observability/profiling.md +++ b/guides/hosting/configurations/observability/profiling.md @@ -34,7 +34,7 @@ The OpenTelemetry profiler is not installed by default. Checkout the [OpenTeleme To add custom spans to the profiler, you can use the `Shopware\Core\Profiling\Profiler::trace` method: -```php +```PHP use Shopware\Core\Profiling\Profiler; $value = Profiler::trace('my-example-trace', function () { @@ -50,7 +50,7 @@ To add a custom profiler backend, you need to implement the `Shopware\Core\Profi The following example shows a custom profiler backend that logs the traces to the console: -```php +```PHP namespace App\Profiler; @@ -70,7 +70,7 @@ class ConsoleProfiler implements ProfilerInterface } ``` -```php +```PHP $services->set(App\Profiler::class) ->tag('shopware.profiler', ['integration' => 'Console']); ``` diff --git a/guides/hosting/performance/session.md b/guides/hosting/performance/session.md index 8ad4b9af47..5ff3acef07 100644 --- a/guides/hosting/performance/session.md +++ b/guides/hosting/performance/session.md @@ -51,14 +51,14 @@ To use one of these handlers, you must create a new service in the dependency in Example service definition: -```php +```PHP $services->set('session.db', Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::class) ->args([/* ... */]); ``` Example session configuration: -```yaml +```YAML # config/packages/redis.yml framework: session: diff --git a/guides/plugins/plugins/bundle.md b/guides/plugins/plugins/bundle.md index 767a9ffdb8..5a46e7f895 100644 --- a/guides/plugins/plugins/bundle.md +++ b/guides/plugins/plugins/bundle.md @@ -67,7 +67,7 @@ If you don't need these features, you can use the Symfony bundle class instead. By default, The namespace `App\` is registered to the `src` folder in any Shopware project to be used for customizations. We recommend using this namespace, if you like to change the project structure, you can change the `App\` namespace in the `composer.json` file of your project. -```php +```PHP // /src/YourBundleName.php /config/bundles.php //... App\YourBundleName\YourBundleName::class => ['all' => true], @@ -104,7 +104,7 @@ You can also add a `theme.json` file to define the theme configuration like [des Migrations are not automatically detected in bundles. To enable migrations, you need to overwrite the `build` method in your bundle class like this: -```php +```PHP // /src/YourBundleName.php --all ``` If you use [Deployment Helper](../../hosting/installation-updates/deployments/deployment-helper.md), you can add it to the `.shopware-project.yaml` file like this: -```yaml +```YAML deployment: hooks: pre-update: | @@ -145,7 +145,7 @@ Shopware-CLI cannot detect bundles automatically, therefore the assets of the bu You will need to adjust the `composer.json` file of your project to specify the path to the bundle. This is done by adding the `extra` section to the `composer.json` file: -```json +```JSON { "extra": { "shopware-bundles": { diff --git a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md index 04b6abedc9..653008631d 100644 --- a/guides/plugins/plugins/checkout/cart/add-cart-discounts.md +++ b/guides/plugins/plugins/checkout/cart/add-cart-discounts.md @@ -23,7 +23,7 @@ To add a discount to the cart, you should use the processor pattern. For this yo Let's start with the actual example code: -```php +```PHP // /src/Core/Checkout/ExampleProcessor.php /src/Service/ExampleController.php /src/Resources/config/services.php /src/Service/ExampleHandler.php /Core/Checkout/Cart/ExampleProcessor.php /src/Resources/config/services.php /src/Core/Checkout/Cart/Custom/CustomCartValidator.php /src/Resources/config/services.php /src/Core/Checkout/Cart/Custom/Error/CustomCartBlockedError.php /src/Resources/snippet/en\_GB/example.en-GB.json { "checkout": { diff --git a/guides/plugins/plugins/checkout/cart/change-price-of-item.md b/guides/plugins/plugins/checkout/cart/change-price-of-item.md index 946b821ed6..e8e5afd795 100644 --- a/guides/plugins/plugins/checkout/cart/change-price-of-item.md +++ b/guides/plugins/plugins/checkout/cart/change-price-of-item.md @@ -39,7 +39,7 @@ Your collector class has to implement the interface `Shopware\Core\Checkout\Cart Let's have a look at an example: -```php +```PHP // /src/Core/Checkout/Cart/OverwritePriceCollector.php /src/Core/Checkout/Cart/OverwritePriceCollector.php /src/Resources/config/services.php /src/Service/CustomProductPriceCalculator.php /src/Resources/config/services.php /src/Checkout/Cart/Tax/TaxProvider.php /src/Resources/config/services.php /src/Migration/MigrationTaxProvider.php /src/BasicExample.php /src/DataResolver/DailyMotionCmsElementResolver.php /src/Service/Subscriber.php -```php +```PHP // /src/Core/Content/Media/TypeDetector/CustomImageTypeDetector.php -```php +```PHP // /src/Resources/config/services.php /src/Subscriber/UnusedMediaSubscriber.php /src/Subscriber/UnusedMediaSubscriber.php private function getUsedMediaIds(array $idsToBeDeleted): array { @@ -123,7 +123,7 @@ by using the tag `kernel.event_subscriber`. -```php +```PHP // /src/Resources/config/services.php /src/Storefront/Controller/ExampleController.php /src/Migration/Migration1619094740AddStaticSeoUrl.php -```php +```PHP // /src/Storefront/Framework/Seo/SeoUrlRoute/ExamplePageSeoUrlRoute.php -```php +```PHP // /src/Resources/config/services.php -```php +```PHP // /src/Service/DynamicSeoUrlPageSubscriber.php -```php +```PHP // /src/Resources/config/services.php /src/Migration/Migration1619514731AddExampleSeoUrlTemplate.php /src/Service/DynamicSeoUrlPageSubscriber.php /src/Service/DynamicSeoUrlsService.php seoUrlPersister->updateSeoUrls($context, self::ROUTE_NAME, $ids, []); @@ -578,7 +578,7 @@ This way the respective SEO URLs will be marked as `is_deleted` for the system. In the example mentioned above, we're just using a `Context` instance, for whichever language that is. You can be more specific here though, in order to properly define the language ID yourself here and therefore ensuring it is written for the right language. -```php +```PHP $context = new Context( $event->getContext()->getSource(), $event->getContext()->getRuleIds(), diff --git a/guides/plugins/plugins/content/seo/extend-robots-txt.md b/guides/plugins/plugins/content/seo/extend-robots-txt.md index ad759587b8..e16c81efde 100644 --- a/guides/plugins/plugins/content/seo/extend-robots-txt.md +++ b/guides/plugins/plugins/content/seo/extend-robots-txt.md @@ -93,7 +93,7 @@ class RobotsExtensionListener -```php +```PHP -```php +```PHP -```php +```PHP -```php +```PHP // /src/Core/Content/Sitemap/Provider/CustomUrlProvider.php -```php +```PHP // /src/Resources/config/services.php -```php +```PHP // /src/Core/Content/Sitemap/Provider/DecoratedProductUrlProvider.php -```php +```PHP // /src/Resources/config/services.php -```php +```PHP // /src/Core/Content/Sitemap/ProductSitemapQuerySubscriber.php -```php +```PHP // /src/Resources/config/services.php -```php +```PHP // /src/Swag/Example/Service/StockStorageDecorator.php -```php +```PHP // /src/Resources/config/services.php -```php +```PHP // /src/Swag/Example/Service/StockStorageDecorator.php -```php +```PHP // /src/Resources/config/services.php 'product-1', 'stock' => 5, @@ -133,7 +133,7 @@ $stockData = \Shopware\Core\Content\Product\Stock\StockData::fromArray([ It is also possible to provide arbitrary data via extensions: -```php +```PHP $stockData = \Shopware\Core\Content\Product\Stock\StockData::fromArray([ 'productId' => 'product-1', 'stock' => 5, @@ -145,6 +145,6 @@ $stockData->addArrayExtension('extraData', ['foo' => 'bar']); The values in the `StockData` instance will be used to update the loaded product instance. Furthermore, fetching the `StockData` instance from the product via the `stock_data` extension is possible. For example: -```php +```PHP $stockData = $product->getExtension('stock_data'); ``` diff --git a/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md b/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md index b91ab70f41..40f10c5da6 100644 --- a/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md +++ b/guides/plugins/plugins/elasticsearch/add-product-entity-extension-to-elasticsearch.md @@ -25,7 +25,7 @@ Here we show you how this could look like in the end. The services.php with all needed definitions. -```php +```PHP // /src/Core/Content/DependencyInjection/product.php /src/Extension/Content/Product/CustomExtension.php /src/Extension/Content/Product/OneToManyExampleExtensionDefinition.php /src/Extension/Content/Product/OneToOneExampleExtensionDefinition.php /src/Elasticsearch/Product/MyProductEsDecorator.php /src/Extension/Content/Product/CustomExtension.php /src/Resources/config/services.php /src/Extension/Content/Product/CustomExtension.php /src/Extension/Content/Product/ExampleExtensionDefinition.php /src/Resources/config/services.php productRepository->upsert([[ 'id' => '', 'exampleExtension' => [ @@ -268,7 +268,7 @@ We can use the DAL event which gets fired every time the product entity is loade Below, you can find an example implementation where we add our extension when the product gets loaded. -```php +```PHP // /src/Subscriber/ProductSubscriber.php /src/Resources/config/services.php set(\Examples\MyBulkExtension::class) ->tag('shopware.bulk.entity.extension'); ``` diff --git a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md index 28bbb4d3b3..f078fcb1ca 100644 --- a/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md +++ b/guides/plugins/plugins/framework/data-handling/add-custom-complex-data.md @@ -27,7 +27,7 @@ In this guide we'll name our table `swag_example`, you'll find this name a few m As already mentioned in the prerequisites, creating a database table is done via plugin migrations [Plugin migrations](../../plugin-fundamentals/database-migrations), head over to this guide to understand how this example works. -```php +```PHP // /src/Migration/Migration1611664789Example.php /src/Core/Content/Example/ExampleDefinition.php`. Below you can see our example definition, which is explained afterwards: -```php +```PHP // /src/Core/Content/Example/ExampleDefinition.php /src/Core/Content/Example/ExampleDefinition.php /src/Core/Content/Example/ExampleEntity.php /src/Core/Content/Example/ExampleDefinition.php class ExampleDefinition extends EntityDefinition { @@ -274,7 +274,7 @@ So create a `ExampleCollection` class in the same directory as your `ExampleDefi This is how your collection class could then look like: -```php +```PHP // /src/Core/Content/Example/ExampleCollection.php /src/Core/Content/Example/ExampleDefinition.php class ExampleDefinition extends EntityDefinition { diff --git a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md index 1abeedc2cb..9d87ff4a02 100644 --- a/guides/plugins/plugins/framework/data-handling/add-data-indexer.md +++ b/guides/plugins/plugins/framework/data-handling/add-data-indexer.md @@ -12,7 +12,7 @@ This guide is built upon the [Plugin base guide](../../plugin-base-guide), but a It is possible to add data indexer for your own entities, like the one created in the [Adding custom complex data](./add-custom-complex-data) guide or for existing entities. However, if you want to react on changes of existing entities the preferred way should be subscribing to the events if available. See the [Index data using existing events](#index-data-using-existing-events) section below. To create a new indexer, just create a new class in your plugin: -```php +```PHP // /src/Core/Framework/DataAbstractionLayer/Indexing/ExampleIndexer.php getPrimaryKeys(CustomerDefinition::ENTITY_NAME); @@ -200,7 +200,7 @@ There are already a bunch of indexers in shopware that you can use. If you take For this we need a new subscriber. If you are not familiar with a subscriber, have a look at our [Listening to events](../../plugin-fundamentals/listening-to-events) guide. For this example, we just write a new entry to the `log_entry` database table, indicating that a customer was updated. -```php +```PHP // /src/Service/Subscriber.php /src/Migration/Migration1612863838ExampleTranslation.php /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationDefinition.php /src/Resources/config/services.php /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationEntity.php /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationDefinition.php class ExampleTranslationDefinition extends EntityTranslationDefinition { @@ -232,7 +232,7 @@ As we already know, we should create an `EntityCollection` for our `Entity` too. Our collection class could then look like this: -```php +```PHP // /src/Core/Content/Example/Aggregate/ExampleTranslation/ExampleTranslationCollection.php /src/Core/Content/Example/ExampleDefinition.php set(Examples\ExampleEntity::class) ->tag('shopware.entity'); ``` @@ -65,7 +65,7 @@ To define more fields, you typically use the `Field` attribute. The `Field` attribute requires the `type` parameter, which is the type of the field. The type can be any of the `FieldType` constants. -```php +```PHP productRepository->search(new Criteria(), $context); @@ -97,7 +97,7 @@ Now let's get into actually filtering your search result to get more precise res Often you have an ID from an entity and you just want to find the whole dataset related to that ID, so here you go: -```php +```PHP public function readData(Context $context): void { $product = $this->productRepository->search(new Criteria([$myId]), $context)->first(); @@ -116,7 +116,7 @@ While searching for an ID will do the trick quite often, you might want to searc In order to do this, you can apply filters to the `Criteria` object, such as an `EqualsFilter`, which accepts a field name and the value to search for. You can find the `EqualsFilter` here: `Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter` -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -138,7 +138,7 @@ For this case, you can combine filters using the `OrFilter` or the `AndFilter`, Let's just build the example mentioned above: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -163,7 +163,7 @@ E.g.: Fetch all products, whose name is `Example product`, but also return the t In that case, you can just use the `addPostFilter` instead of `addFilter`: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -183,7 +183,7 @@ There is more than just an `EqualsFilter`, which is the SQL equivalent of `WHERE Of course associations to other entities are also possible in Shopware 6. If you, for example, want to load all product-reviews, which is an entity itself, related to the product you have found, you can do so by adding associations to the criteria object. -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -198,7 +198,7 @@ Just like the available entity fields, you can find all possible associations in Also worth to mention is the fact, that you can chain the association key. E.g. a product-review has another association to the customer, who created that review. If you want access to both the review itself, as well as the customer, you can just write the association like that: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -215,7 +215,7 @@ Yes, this is doable. You can apply filters to an association. E.g. "Add all prod For this we can use `getAssociation` instead, which basically returns its own `Criteria` object, on which you can apply a filter. -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -233,7 +233,7 @@ Once again: Note, that we used `getAssociation` here now instead of `addAssociat Another example to clarify what's going on here: -```php +```PHP public function readData(Context $context): void { // This will always return the product with the given name, no matter if it has a review with 4 or more stars. @@ -260,7 +260,7 @@ Every `ManyToMany` association comes with a mapping entity, such as the `Product The following example will **not** work: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -276,7 +276,7 @@ Since mapping entities just consist of two primary keys, there is no need to sea Of course you can also aggregate your data. Just like filters and associations, this can be done by using an `addAggregation` method on the `Criteria` object. Let's create an example aggregation, that returns the average rating for a product: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -300,7 +300,7 @@ There's just a few more things missing: Limiting your result intentionally to e. Let's start with the limiting of the result: -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -313,7 +313,7 @@ public function readData(Context $context): void That's quite self-explanatory, isn't it? Just use the `setLimit` method with your desired limit as parameter. Little spoiler: It's the same for the offset! -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -327,7 +327,7 @@ public function readData(Context $context): void This way you get the 2nd possible product. But since you didn't define a sorting yourself, the result can be quite confusing, so let's add a sorting. -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -352,7 +352,7 @@ Imagine you need to iterate over all products of your shop, which contains more Instead, the `RepositoryIterator` will return a batch of data, which size you can define, with each iteration. Just be sure to not use it unnecessarily, since it will create a new database request with each iteration, which is not needed for smaller chunks of data. -```php +```PHP public function readData(Context $context): void { $criteria = new Criteria(); @@ -376,7 +376,7 @@ Put differently, you must ensure that your sorting means that there's only one c For example, ordering products by `manufacturerNumber` alone could cause this issue, because several products can have the same `manufacturerNumber`, so there's several correct orderings of those products. On the other hand, because each product is guaranteed to have a unique ID, sorting by ID is an easy way to mitigate this issue: -```php +```PHP $criteria = new Criteria(); //This sorting alone would result in sorting that is nondeterministic as several products might have the same value for this field: $criteria->addSorting(new FieldSorting('manufacturerNumber')); diff --git a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md index 4ee9982f5e..f9aadc4be3 100644 --- a/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md +++ b/guides/plugins/plugins/framework/data-handling/replacing-associated-data.md @@ -25,7 +25,7 @@ So let's start with the main issue going on here. Let's imagine you've created a The following example will show you how **not** to do it. It's assuming that you've previously assigned the category `Old category` with the ID `oldId` to the product. -```php +```PHP public function replaceData(Context $context): void { $this->productRepository->update([ @@ -55,7 +55,7 @@ In order to delete it, we once again need its repository. The name for the entit So let's inject this repository into our class called `ReplacingData`: -```php +```PHP // SwagBasicExample/src/Resources/config/services.php productCategoryRepository->delete([ @@ -91,7 +91,7 @@ public function replaceData(Context $context): void Now the association to the old category was removed and you can now use the code above to add the new category instead. -```php +```PHP public function replaceData(Context $context): void { $productId = 'myProductId'; @@ -122,7 +122,7 @@ And that's it, you've successfully deleted one association and then replaced it Replacing `OneToOne` or `ManyToOne` associations works just like expected via an `update` call, e.g. for the tax of a product: -```php +```PHP public function replaceData(Context $context): void { $this->productRepository->update([ diff --git a/guides/plugins/plugins/framework/data-handling/using-database-events.md b/guides/plugins/plugins/framework/data-handling/using-database-events.md index 853c83283c..cd1864a285 100644 --- a/guides/plugins/plugins/framework/data-handling/using-database-events.md +++ b/guides/plugins/plugins/framework/data-handling/using-database-events.md @@ -36,7 +36,7 @@ You can use this event to capture state, perform actions, and sync data after an Below is an example subscriber listening to the generic entity write event and logging the ID's of the written entities. -```php +```PHP // /src/Subscriber/EntityWriteSubscriber.php /src/Subscriber/DeleteSubscriber.php /src/Subscriber/ProductSubscriber.php /src/Resources/config/services.php productRepository->create([ @@ -109,7 +109,7 @@ private function getTaxId(Context $context): string First of all, for this example you'll need the following new imports: -```php +```PHP use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; @@ -134,7 +134,7 @@ And that's it, this will write and create your first entity, a product. Of cours In Shopware 6 we're using UUIDs for the ID fields in the entities. This comes with a major advantage: You can define your IDs when creating an entity already and thus do not have to figure out which ID your newly created entity received, e.g. by auto-increment. -```php +```PHP public function writeData(): void { $context = Context::createDefaultContext(); @@ -168,7 +168,7 @@ So note the `id` field we've provided now - even though you're just creating you So what if you don't want to create a new entity, but rather update an existing one? For that case, you can use the `update` method on the repository. Let's just update our previously created product and change its name. -```php +```PHP public function writeData(Context $context): void { $criteria = new Criteria(); @@ -201,7 +201,7 @@ In order to create data, we've used the `create` method. For updating data, we'v Here's an example on how to delete the previously created product: -```php +```PHP public function writeData(Context $context): void { $criteria = new Criteria(); @@ -229,7 +229,7 @@ If you don't know how to add associations to an entity, maybe to your own entity Earlier in this guide, you created a product and used an existing tax entity for that case. This is representing a ManyToOne association, but OneToOne associations are handled the same. -```php +```PHP public function writeData(Context $context): void { $this->productRepository->create([ @@ -260,7 +260,7 @@ OneToMany and ManyToMany associations are handled the same. An example in the product context would be assigning a category to a product. -```php +```PHP public function writeData(Context $context): void { $criteria = new Criteria(); @@ -292,7 +292,7 @@ Every `ManyToMany` association comes with a mapping entity. It's important to kn The following example will fail: -```php +```PHP public function writeData(Context $context): void { // This is the product_category.repository service @@ -313,7 +313,7 @@ Your only way to solve this is by replacing the association. Head over to our gu So you don't want to assign an existing tax entity when creating a product, but rather you'd like to create a new tax entity in the same step. That is also possible, and this section will show you an example on how to do it. -```php +```PHP public function writeData(Context $context): void { $this->productRepository->create([ @@ -334,7 +334,7 @@ In order to create a tax entity while creating the product, you have to provide And that's already it - now the tax will be created in the same step when the product is created and will be assigned automatically. This works almost the same for `ToMany` associations. -```php +```PHP public function writeData(Context $context): void { $this->productRepository->create([ diff --git a/guides/plugins/plugins/framework/event/finding-events.md b/guides/plugins/plugins/framework/event/finding-events.md index c10715e1aa..787e19f6c8 100644 --- a/guides/plugins/plugins/framework/event/finding-events.md +++ b/guides/plugins/plugins/framework/event/finding-events.md @@ -33,7 +33,7 @@ Finding those "event classes" can be done by searching for the term `@Event` in You can use those events in a [subscriber](../../plugin-fundamentals/listening-to-events) like the following: -```php +```PHP public static function getSubscribedEvents(): array { return [ @@ -48,7 +48,7 @@ As you can see, you can either use the event class constants, if available, or t You'll then have access to several event specific information, e.g. your listener method will have access to an [EntityWrittenEvent](https://github.com/shopware/shopware/blob/v6.4.0.0/src/Core/Framework/DataAbstractionLayer/Event/EntityWrittenEvent.php) instance when subscribing to the `written` event. -```php +```PHP public function onCustomEntityWritten(EntityWrittenEvent $event): void { } @@ -72,7 +72,7 @@ There are multiple ways to find them: You will most likely look into our Core code quite a lot, while trying to understand what's happening and why things are happening. On your journey looking through the code, you may stumble upon code looking like this: -```php +```PHP $someEvent = new SomeEvent($parameters, $moreParameters); $this->eventDispatcher->dispatch($someEvent, $someEvent->getName()); ``` @@ -85,7 +85,7 @@ If the second parameter is not applied, the class name will be used as a fallbac When subscribing to those events, your event listener method will have access to the previously created event instance. -```php +```PHP public static function getSubscribedEvents(): array { return [ @@ -121,7 +121,7 @@ Every service, that wants to fire an event sooner or later, needs access to the Hence, you can have a look at all the service definitions for the [Dependency injection container](../../plugin-fundamentals/dependency-injection) and therefore quickly figure out, which services and classes are having access to the said `event_dispatcher`: -```php +```PHP 'product'])] public function load(string $categoryId, Request $request, SalesChannelContext $context, Criteria $criteria): ProductListingRouteResponse { @@ -220,7 +220,7 @@ Therefore, we have added fine-grained route events that are thrown for every rou To subscribe to a specific event, replace the `{route}` placeholder with the [actual symfony route name](https://symfony.com/doc/current/routing.html), e.g. `store-api.product.listing`. -```php +```PHP public static function getSubscribedEvents(): array { return [ diff --git a/guides/plugins/plugins/framework/extension/creating-custom-extension.md b/guides/plugins/plugins/framework/extension/creating-custom-extension.md index 9d8aef0534..f86944f5a5 100644 --- a/guides/plugins/plugins/framework/extension/creating-custom-extension.md +++ b/guides/plugins/plugins/framework/extension/creating-custom-extension.md @@ -17,7 +17,7 @@ While Shopware provides many built-in extension points, you may need to create c All extension points must extend the base `Extension` class and define a typed result: -```php +```PHP set(MyPlugin\Service\CustomProductService::class) ->args([ @@ -252,7 +252,7 @@ $services->set(MyPlugin\Subscriber\CustomProductFilterSubscriber::class) ### 1. Conditional Extension Execution -```php +```PHP public function onExtension(MyExtension $event): void { // Only execute under certain conditions @@ -272,7 +272,7 @@ private function shouldExecute(MyExtension $event): bool ### 2. Extension with Error Handling -```php +```PHP public function onExtension(MyExtension $event): void { try { @@ -293,7 +293,7 @@ public function onExtension(MyExtension $event): void ### 3. Extension with Data Enrichment -```php +```PHP public function onExtension(MyExtension $event): void { // Don't replace the result, just enrich it @@ -317,7 +317,7 @@ private function enrichResult($result, MyExtension $event) ### 4. Multi-Phase Extension -```php +```PHP public static function getSubscribedEvents(): array { return [ @@ -418,7 +418,7 @@ Use `.error` events to: Here's a complete example of a plugin that creates and uses a custom extension point: -```php +```PHP // 1. Extension class final class ProductRecommendationExtension extends Extension { diff --git a/guides/plugins/plugins/framework/extension/finding-extensions.md b/guides/plugins/plugins/framework/extension/finding-extensions.md index 51b55dbc9e..b4bc923b82 100644 --- a/guides/plugins/plugins/framework/extension/finding-extensions.md +++ b/guides/plugins/plugins/framework/extension/finding-extensions.md @@ -42,7 +42,7 @@ Here are some common Extension Point you might encounter: #### Product Extensions -```php +```PHP // Product price calculation src/Core/Content/Product/Extension/ProductPriceCalculationExtension.php @@ -55,7 +55,7 @@ src/Core/Content/Product/Extension/ProductListingCriteriaExtension.php #### Cart Extensions -```php +```PHP // Checkout place order src/Core/Checkout/Cart/Extension/CheckoutPlaceOrderExtension.php @@ -65,7 +65,7 @@ src/Core/Checkout/Cart/Extension/CheckoutCartRuleLoaderExtension.php #### CMS Extensions -```php +```PHP // CMS slots data enrichment src/Core/Content/Cms/Extension/CmsSlotsDataEnrichExtension.php @@ -81,7 +81,7 @@ Extension Points follow a consistent naming pattern: Extension Points use a `NAME` constant that defines the event name: -```php +```PHP final class ResolveListingExtension extends Extension { public const NAME = 'listing-loader.resolve'; @@ -104,7 +104,7 @@ Extension Points are dispatched with lifecycle suffixes: Services that use Extension Points typically inject the `ExtensionDispatcher`: -```php +```PHP $services->set(Some\Service::class) ->args([service(Shopware\Core\Framework\Extensions\ExtensionDispatcher::class)]); ``` @@ -113,7 +113,7 @@ $services->set(Some\Service::class) Look for services that inject the `ExtensionDispatcher`: -```php +```PHP public function __construct( private readonly ExtensionDispatcher $extensionDispatcher ) { @@ -124,7 +124,7 @@ public function __construct( Extension Points are typically dispatched using this pattern: -```php +```PHP $extension = new SomeExtension($parameters); $result = $this->extensionDispatcher->publish( SomeExtension::NAME, @@ -146,7 +146,7 @@ $result = $this->extensionDispatcher->publish( **Event Name**: `product.calculate-prices` **Return Type**: `void` -```php +```PHP final class ProductPriceCalculationExtension extends Extension { public const NAME = 'product.calculate-prices'; @@ -164,7 +164,7 @@ final class ProductPriceCalculationExtension extends Extension **Event Name**: `listing-loader.resolve` **Return Type**: `EntitySearchResult` -```php +```PHP final class ResolveListingExtension extends Extension { public const NAME = 'listing-loader.resolve'; @@ -184,7 +184,7 @@ final class ResolveListingExtension extends Extension **Event Name**: `checkout.place-order` **Return Type**: `OrderPlaceResult` -```php +```PHP final class CheckoutPlaceOrderExtension extends Extension { public const NAME = 'checkout.place-order'; @@ -204,7 +204,7 @@ final class CheckoutPlaceOrderExtension extends Extension **Event Name**: `cms.slots.data-enrich` **Return Type**: `CmsSlotCollection` -```php +```PHP final class CmsSlotsDataEnrichExtension extends Extension { public const NAME = 'cms.slots.data-enrich'; @@ -222,7 +222,7 @@ final class CmsSlotsDataEnrichExtension extends Extension Create an event subscriber to listen for Extension Points: -```php +```PHP set(MyPlugin\Subscriber\ProductListingSubscriber::class) ->tag('kernel.event_subscriber'); ``` @@ -268,7 +268,7 @@ Extension Points follow a specific lifecycle: ### Lifecycle Example -```php +```PHP public function handleExtension(SomeExtension $event): void { // This runs in the .pre phase @@ -291,7 +291,7 @@ public function handlePostExtension(SomeExtension $event): void Always use proper type hints for Extension Point parameters: -```php +```PHP public function onResolveListing(ResolveListingExtension $event): void { // Type-safe access to properties @@ -304,7 +304,7 @@ public function onResolveListing(ResolveListingExtension $event): void Check if a result has already been set: -```php +```PHP public function onExtension(SomeExtension $event): void { if ($event->result !== null) { @@ -320,7 +320,7 @@ public function onExtension(SomeExtension $event): void Only stop propagation when you're providing a complete replacement: -```php +```PHP public function onExtension(SomeExtension $event): void { if ($this->shouldReplaceDefault($event)) { @@ -335,7 +335,7 @@ public function onExtension(SomeExtension $event): void Extension Points have built-in error handling, but you can also handle errors gracefully: -```php +```PHP public function onExtension(SomeExtension $event): void { try { @@ -358,7 +358,7 @@ The Symfony profiler shows all dispatched Extension Points in the "Events" tab. You can log Extension Point calls to understand the flow: -```php +```PHP public function onExtension(SomeExtension $event): void { $this->logger->debug('Extension called', [ diff --git a/guides/plugins/plugins/framework/filesystem/filesystem.md b/guides/plugins/plugins/framework/filesystem/filesystem.md index 619f9d4573..a56e418bc9 100644 --- a/guides/plugins/plugins/framework/filesystem/filesystem.md +++ b/guides/plugins/plugins/framework/filesystem/filesystem.md @@ -34,7 +34,7 @@ However, every plugin/bundle gets an own namespace that should be used for priva To make use of the filesystem, we register a new service, which helps to read and write files to the filesystem. -```php +```PHP // /src/Service/ExampleFilesystemService.php /src/Resources/config/services.php /src/Core/Framework/Event`. Our new interface has to extend from interfaces `Shopware\Core\Framework\Event\FLowEventAware`: -```php +```PHP // /src/Core/Framework/Event/TagAware.php /src/Core/Content/Flow/Dispatching/Action`. Below you can find an example implementation: -```php +```PHP // /src/Core/Content/Flow/Dispatching/Action/CreateTagAction.php /src/Resources/config/services.php`. This tag will ensure that your action is included in the response of the *`/api/_info/flow-actions.json`* API. The priority attribute will determine the order of the action in the API response. -```php +```PHP // /src/Resources/config/services.php $services->set(Swag\CreateTagAction\Core\Content\Flow\Dispatching\Action\CreateTagAction::class) ->args([service('tag.repository')]) @@ -162,7 +162,7 @@ There are three scopes for the `CreateTagAction`: - Just define the empty array in `CreateTagAction::requirements` -```php +```PHP // plugin root>/src/Core/Content/Flow/Dispatching/Action/CreateTagAction.php ... @@ -184,7 +184,7 @@ Here, the action name is empty as the action name snippet is not yet defined. Make the `CreateTagAction` available for all events related to Order and Customer. -```php +```PHP // /src/Core/Content/Flow/Dispatching/Action/CreateTagAction.php ... @@ -202,7 +202,7 @@ Make the `CreateTagAction` available for all events related to Order and Custome - Event must implement the `TagAware` -```php +```PHP // /src/Core/Content/Flow/Subscriber/BusinessEventCollectorSubscriber.php /src/Core/Content/Flow/Dispatching/Action/CreateTagAction.php ... @@ -269,7 +269,7 @@ class BasicExampleEvent extends Event implements TagAware - To show the new event in Flow Builder Triggers list -```php +```PHP // /src/Core/Content/Subscriber/BusinessEventCollectorSubscriber.php /src/Resources/config/services.php`. -```php +```PHP $services->set(Swag\CreateTagAction\Core\Content\Subscriber\BusinessEventCollectorSubscriber::class) ->args([service(Shopware\Core\Framework\Event\BusinessEventCollector::class)]) @@ -321,7 +321,7 @@ $services->set(Swag\CreateTagAction\Core\Content\Subscriber\BusinessEventCollect - Define the Event snippet -```json +```JSON // /src/Resources/app/administration/src/module/sw-flow/snippet/en-GB.json { "sw-flow": { diff --git a/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md b/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md index 28ec3682ea..367a04fa27 100644 --- a/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md +++ b/guides/plugins/plugins/framework/flow/add-flow-builder-trigger.md @@ -52,7 +52,7 @@ In this example, we will name it ExampleEvent to some actions related to custome Below you can find an example implementation: -```php +```PHP // /src/Core/Checkout/Customer/Event/ExampleEvent.php /src/Core/Checkout/Customer/Subscriber/BusinessEventCollectorSubscriber.php /src/Core/Checkout/Customer/Subscriber/BusinessEventCollectorSubscriber.php public static function getSubscribedEvents() { @@ -394,7 +394,7 @@ public static function getSubscribedEvents() And remember to register your subscriber to the container at `/src/Resources/config/services.php` -```php +```PHP // /src/Resources/config/services.php $services->set(Swag\ExamplePlugin\Core\Checkout\Customer\Subscriber\BusinessEventCollectorSubscriber::class) ->args([service(Shopware\Core\Framework\Event\BusinessEventCollector::class)]) diff --git a/guides/plugins/plugins/framework/rule/add-custom-rules.md b/guides/plugins/plugins/framework/rule/add-custom-rules.md index 0962b7f1d2..64edc5a371 100644 --- a/guides/plugins/plugins/framework/rule/add-custom-rules.md +++ b/guides/plugins/plugins/framework/rule/add-custom-rules.md @@ -29,7 +29,7 @@ To create a custom rule, we have to implement both backend \(PHP\) code and a us First of all, we need a new Rule class. In this example, we name it as `FirstMondayOfTheMonthRule`. It will be placed in the directory `/src/Core/Rule`. Our new class has to extend from the abstract class `Shopware\Core\Framework\Rule\Rule`. Below you can find an example implementation. -```php +```PHP // /src/Core/Rule/FirstMondayOfTheMonthRule.php getSalesChannelContext()->getCustomer(); $loggedIn = $customer !== null; @@ -121,7 +121,7 @@ $loggedIn = $customer !== null; It is possible to add config to our rule. This makes it possible to skip the [Custom rule component](#custom-rule-component) and the [Custom rule Administration template](#custom-rule-administration-template) parts. -```php +```PHP public function getConfig(): RuleConfig { return (new RuleConfig())->booleanField('isFirstMondayOfTheMonth'); @@ -134,7 +134,7 @@ when [Showing rule in the Administration](#showing-rule-in-the-administration) w You can access all active rules by using the `getRuleIds` method of the context. -```php +```PHP $context->getRuleIds(); ``` diff --git a/guides/plugins/plugins/framework/store-api/add-store-api-route.md b/guides/plugins/plugins/framework/store-api/add-store-api-route.md index 170718ec1c..d5bcb466cc 100644 --- a/guides/plugins/plugins/framework/store-api/add-store-api-route.md +++ b/guides/plugins/plugins/framework/store-api/add-store-api-route.md @@ -29,7 +29,7 @@ All fields that should be available through the API require the flag `ApiAware` First of all, we create an abstract class called `AbstractExampleRoute`. This class has to contain a method `getDecorated` and a method `load` with a `Criteria` and `SalesChannelContext` as parameter. The `load` method has to return an instance of `ExampleRouteResponse`, which we will create later on. -```php +```PHP // /src/Core/Content/Example/SalesChannel/AbstractExampleRoute.php /src/Core/Content/Example/SalesChannel/ExampleRoute.php /src/Core/Content/Example/SalesChannel/ExampleRouteResponse.php /src/Resources/config/` location. Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. -```php +```PHP // /src/Resources/config/routes.php /src/Resources/Schema/StoreApi/` so the shopware internal OpenApi3Generator can find it (for Admin API endpoints, use `AdminApi`). -```javascript +```JAVASCRIPT // /src/Resources/Schema/StoreApi/example.json { "openapi": "3.0.0", @@ -226,7 +226,7 @@ Your generated request and response could look like this: #### Request -```json +```JSON { "page": 0, "limit": 0, @@ -278,7 +278,7 @@ Your generated request and response could look like this: #### Response -```json +```JSON { "total": 0, "aggregations": {}, @@ -299,7 +299,7 @@ Your generated request and response could look like this: If you want to access the functionality of your route also from the Storefront you need to make it available there by adding a custom [Storefront controller](../../storefront/add-custom-controller) that will wrap your just created route. -```php +```PHP // /src/Storefront/Controller/ExampleController.php true` config option on the ro ### Register the Controller -```php +```PHP /src/Resources/config/routes.php /src/Resources/app/storefront/src/example-plugin/example-plugin.plugin.js const { PluginBaseClass } = window; @@ -397,7 +397,7 @@ export default class ExamplePlugin extends PluginBaseClass { offset: 0, }), }); - + if (!response.ok) { throw new Error('Request failed'); } diff --git a/guides/plugins/plugins/framework/store-api/override-existing-route.md b/guides/plugins/plugins/framework/store-api/override-existing-route.md index 73d454ac5d..303160dbd1 100644 --- a/guides/plugins/plugins/framework/store-api/override-existing-route.md +++ b/guides/plugins/plugins/framework/store-api/override-existing-route.md @@ -21,7 +21,7 @@ Furthermore, you should have a look at our guide about [Adding a Store API route First, we have to create a new class which extends `AbstractExampleRoute`. In this example we will name it `ExampleRouteDecorator`. -```php +```PHP // /src/Core/Content/Example/SalesChannel/ExampleRouteDecorator.php /src/Resources/config/services.php set(YourNameSpace\LocalDiskSpaceCheck::class) ->args([ '%shopware.filesystem.public.type%', diff --git a/guides/plugins/plugins/framework/system-check/index.md b/guides/plugins/plugins/framework/system-check/index.md index b7e54e2296..26dc9ad41b 100644 --- a/guides/plugins/plugins/framework/system-check/index.md +++ b/guides/plugins/plugins/framework/system-check/index.md @@ -37,7 +37,7 @@ The `SystemChecker` class makes sure the system is working correctly by running All the system checks in Shopware are tagged with `shopware.system_check`, so you can also fetch all the checks using the Symfony service locator. and run them in your custom flow. -```php +```PHP class CustomSystemChecker { public function __construct(private readonly iterable $checks) @@ -51,7 +51,7 @@ class CustomSystemChecker } ``` -```php +```PHP $services->set(YourNamepace\CustomSystemChecker::class) ->args([tagged_iterator('shopware.system_check')]); ``` @@ -60,7 +60,7 @@ $services->set(YourNamepace\CustomSystemChecker::class) For customized triggers, you can also inject the `Shopware\Core\Framework\SystemCheck\SystemChecker` service into your service and trigger the checks programmatically. -```php +```PHP $results = $systemChecker->check(SystemCheckExecutionContext::WEB); # or also use any custom logic you might have... $customChecker->check(); diff --git a/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md b/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md index 90ecd35a27..162c862b63 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-custom-commands.md @@ -11,7 +11,7 @@ Shopware CLI commands are based on [Symfony Console](https://symfony.com/doc/cur To add a custom command in a Shopware plugin, you must register it as a service in your plugin's `src/Resources/config/services.php` and tag it with `console.command`: -```php +```PHP $services->set(Swag\BasicExample\Command\ExampleCommand::class) ->tag('console.command'); ``` diff --git a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md index 6c09c597af..23b234f5a0 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-scheduled-task.md @@ -25,7 +25,7 @@ A `ScheduledTask` and its respective `ScheduledTaskHandler` are registered in a Here's an example `services.php` containing a new `ScheduledTask` as well as a new `ScheduledTaskHandler`: -```php +```PHP // /src/Resources/config/services.php /src/Service/ScheduledTask/ExampleTask.php /src/Service/ScheduledTask/ExampleTaskHandler.php /src/Resources/config/services.php /src/Service/AbstractExampleService.php /src/Service/ExampleService.php /src/Service/ExampleServiceDecorator.php /src/Service/AbstractExampleService.php /src/Service/ExampleService.php /src/Subscriber/MySubscriber.php /src/Subscriber/MySubscriber.php /src/Resources/config/services.php /src/Subscriber/MySubscriber.php /src/Resources/config/config.xml /src/Resources/config/services.php /src/Subscriber/MySubscriber.php .config.`. Thus, it would be `SwagBasicExample.config.example` here. -```php +```PHP // /src/Subscriber/MySubscriber.php window.pluginConfig = { @@ -228,7 +228,7 @@ For Storefront JavaScript plugins, you can pass configuration values from Twig t ``` -```javascript +```JAVASCRIPT // In your Storefront JavaScript plugin const { PluginBaseClass } = window; @@ -236,7 +236,7 @@ export default class ExamplePlugin extends PluginBaseClass { init() { // Access the configuration value passed from Twig const exampleConfig = window.pluginConfig?.example; - + if (exampleConfig) { console.log('Plugin configuration:', exampleConfig); // Use the configuration value in your plugin logic diff --git a/guides/plugins/plugins/storefront/add-cookie-to-manager.md b/guides/plugins/plugins/storefront/add-cookie-to-manager.md index d08c8d8d14..c84e523708 100644 --- a/guides/plugins/plugins/storefront/add-cookie-to-manager.md +++ b/guides/plugins/plugins/storefront/add-cookie-to-manager.md @@ -31,7 +31,7 @@ It is recommended to use an event listener if you're listening to a single event Start with creating the `services.php` and registering your event listener. -```php +```PHP // /src/Resources/config/services.php /src/Listener/CookieListener.php set(\Swag\BasicExample\Service\AddDataToPage::class) ->tag('kernel.event_subscriber'); @@ -93,7 +93,7 @@ First you should read our guide for [adding store-api routes](../framework/store Our new Route should look like this: -```php +```PHP /src/Resources/config/routes.php -```php +```PHP /src/Resources/config/services.php"> -```php +```PHP /src/Resources/config/config.xml /src/Resources/config/config.xml -```php +```PHP /src/Resources/config/services.php"> -```php +```PHP addVariable()` for every field individually may be a bit cumbersome in some cases. You could also loop over all config fields and call `addVariable()` for each one. However, this depends on your use case. -```php +```PHP // /src/Subscriber/ThemeVariableSubscriber.php trans('header.example'); ``` Translation with placeholders: -```php +```PHP $this->trans('soldProducts', ['%count%' => 3, '%country%' => 'Germany']); ``` @@ -114,13 +114,13 @@ If we need to use a snippet elsewhere in PHP, we can use [Dependency Injection](../plugin-fundamentals/dependency-injection) to inject the `translator` service, which implements Symfony's `Symfony\Contracts\Translation\TranslatorInterface`: -```php +```PHP $services->set(Swag\Example\Service\SwagService::class) ->public() ->args([service('translator')]); ``` -```php +```PHP private TranslatorInterface $translator; public function __construct(TranslatorInterface $translator) @@ -131,6 +131,6 @@ public function __construct(TranslatorInterface $translator) Then, call the `trans` method, which has the same parameters as the method from controllers. -```php +```PHP $this->translator->trans('soldProducts', ['%count%' => 3, '%country%' => 'Germany']); ``` diff --git a/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md b/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md index 522cbb8bd3..f74611a939 100644 --- a/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md +++ b/products/extensions/advanced-search/How-to-add-more-fields-to-product-search.md @@ -13,7 +13,7 @@ In this example, we create a field called `productNumberPrefix` to make it searc **1. Decorate the ElasticsearchDefinition** -```php +```PHP $services->set(YourPluginNameSpace\ElasticsearchProductDefinitionDecorator::class) ->decorate(Shopware\Elasticsearch\Product\ElasticsearchProductDefinition::class) ->args([ @@ -22,7 +22,7 @@ $services->set(YourPluginNameSpace\ElasticsearchProductDefinitionDecorator::clas ]); ``` -```php +```PHP set(YourPluginNameSpace\Domain\Search\SearchLogicDecorator::class) ->decorate(Shopware\Commercial\AdvancedSearch\Domain\Search\SearchLogic::class) ->args([ @@ -28,7 +28,7 @@ $services->set(YourPluginNameSpace\Domain\Search\SearchLogicDecorator::class) ]); ``` -```php +```PHP set(YourPluginNameSpace\CartAmountRule::class) ->public() ->tag('shopware.approval_rule.definition'); diff --git a/products/extensions/b2b-suite-migration/development/handler.md b/products/extensions/b2b-suite-migration/development/handler.md index ea96324741..c4e735fc4c 100644 --- a/products/extensions/b2b-suite-migration/development/handler.md +++ b/products/extensions/b2b-suite-migration/development/handler.md @@ -76,7 +76,7 @@ Handlers allow custom logic to transform data before mapping it to the target fi To use a handler, implement a PHP class (e.g., `RolePermissionsTransformer`) that extends `Shopware\Commercial\B2B\B2BSuiteMigration\Core\Domain\DataTransformer\AbstractFieldTransformer` and tag it with `b2b.migration.transformer` in your service configuration. -```php +```PHP $services->set(Shopware\Commercial\B2B\B2BSuiteMigration\Components\QuoteManagement\DataTransformer\QuoteComment\StateTransformer::class) ->lazy() ->args([service(Shopware\Core\Framework\Extensions\ExtensionDispatcher::class)]) diff --git a/products/extensions/b2b-suite/guides/core/authentication.md b/products/extensions/b2b-suite/guides/core/authentication.md index b1149b053b..3320e81209 100644 --- a/products/extensions/b2b-suite/guides/core/authentication.md +++ b/products/extensions/b2b-suite/guides/core/authentication.md @@ -54,7 +54,7 @@ CREATE TABLE IF NOT EXISTS `b2b_my` ( This modifier column allows you to store the context owner independent of the actual source table of the context owner. You can access the current context owner always through the identity. -```php +```PHP [...] /** @var AuthenticationService $authenticationService */ @@ -75,7 +75,7 @@ echo 'The context owner id ' . $ownershipContext->contextOwnerId . '\n'; You can even load the whole identity through the `AuthenticationService`. -```php +```PHP [...] $ownerIdentity = $authenticationService->getIdentityByAuthId($contextOwnerId); @@ -87,7 +87,7 @@ $ownerIdentity = $authenticationService->getIdentityByAuthId($contextOwnerId); Sometimes you want to flag records to be owned by certain identities. -```sql +```SQL CREATE TABLE IF NOT EXISTS `b2b_my` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `auth_id` INT(11) NULL DEFAULT NULL, @@ -103,7 +103,7 @@ CREATE TABLE IF NOT EXISTS `b2b_my` ( To fill this column, we again access the current identity, but instead of the `contextOwnerId`, we access the `authId`. -```php +```PHP [...] $ownershipContext = $authenticationService @@ -119,7 +119,7 @@ The B2B Suite views the context owner as some kind of admin that, from the persp Therefore, commonly used queries are: -```php +```PHP /** @var Connection $connection */ $connection = $this->container->get('dbal_connection'); /** @var Identity $identity */ @@ -174,11 +174,11 @@ Example implementations are either: `Shopware\B2B\Debtor\Framework\DebtorIdentit In the *CredentialsBuilder*, you create the *CredentialsEntity*, which is used for logging in the B2B Suite. -```php +```PHP public function createCredentials(array $parameters): AbstractCredentialsEntity { $entity = new CredentialsEntity(); - + $entity->email = $parameters['email']; $entity->salesChannelId = IdValue::create($this->contextProvider->getSalesChannelContext()->getSalesChannel()->getId()); $entity->customerScope = $this->systemConfigService->get('core.systemWideLoginRegistration.isCustomerBoundToSalesChannel'); @@ -196,23 +196,23 @@ Next, you have to provide the means to register your identity on login. This is The *LoginContextService* is passed as an argument to help you retrieve and create the appropriate auth and context owner ids. Notice that the interface is designed to be chained to create dependent auth ids on the fly. -```php +```PHP [...] public function fetchIdentityByCredentials(CredentialsEntity $credentialsEntity, LoginContextService $contextService, bool $isApi = false): Identity { if (!$credentialsEntity->email) { throw new NotFoundException('Unable to handle context'); } - + $entity = $this->yourEntityRepository->fetchOneByEmail($email); /** @var DebtorIdentity $debtorIdentity */ $debtorIdentity = $this->debtorRepository->fetchIdentityById($entity->debtor->id, $contextService); - + $authId = $contextService->getAuthId(YourEntityRepository::class, $entity->id, $debtorIdentity->getAuthId()); - + $this->yourEntityRepository->setAuthId($entity->id, $authId); - + return new YourEntityIdentity($authId, (int) $entity->id, YourEntityRepository::TABLE_NAME, $entity, $debtorIdentity); } [...] @@ -220,7 +220,7 @@ context owner ids. Notice that the interface is designed to be chained to create Finally, you register your authentication provider (in our case a repository) as a tagged service through the DIC. -```php +```PHP $services->set('b2b_my.contact_authentication_identity_loader', Shopware\B2B\My\AuthenticationIdentityLoader::class) // [...] ->tag('b2b_front_auth.authentication_repository'); diff --git a/products/extensions/b2b-suite/guides/core/entity-acl.md b/products/extensions/b2b-suite/guides/core/entity-acl.md index d6d140b9da..a8690764e6 100644 --- a/products/extensions/b2b-suite/guides/core/entity-acl.md +++ b/products/extensions/b2b-suite/guides/core/entity-acl.md @@ -73,7 +73,7 @@ The address ACL repository can be retrieved through the DIC by the `b2b_address. The repository then provides the following methods. If you are already familiar with other ACL implementations, most methods will look quite familiar. -```php +```PHP container->get('b2b_address.acl_repository'); $contactRepository = $this->container->get('b2b_contact.repository'); @@ -209,7 +209,7 @@ $aclAddressRepository->allow( We can then deny the access just by this: -```php +```PHP $aclAdressRepository->deny( $contact, // the contact 22, // the id of the address @@ -218,7 +218,7 @@ $aclAdressRepository->deny( or just set it not grantable, by -```php +```PHP $aclAdressRepository->allow( $contact, // the contact 22, // the id of the address @@ -230,7 +230,7 @@ $aclAdressRepository->allow( If you want to know whether a certain contact can access an entity, you can call `isAllowed`. -```php +```PHP $aclAdressRepository->isAllowed( $contact, // the contact 22, // the id of the address @@ -239,7 +239,7 @@ $aclAdressRepository->isAllowed( Or you just want to check whether an entity can be granted by a contact. -```php +```PHP $aclAdressRepository->isGrantable( $contact, // the contact 22, // the id of the address @@ -250,7 +250,7 @@ One of the more complex problems you might face is that you want to filter a que This can be achieved by this snippet: -```php +```PHP address` relation. Now we need to tell the B2B Suite to create the necessary tables. In Shopware, this must be done during the plugin installation process. Because the container is not yet set up with the B2B Suite services, we use a static factory method in the following code: -```php +```PHP use Shopware\B2B\Acl\Framework\AclDdlService; use Shopware\B2B\Address\Framework\AddressContactTable; @@ -343,14 +343,14 @@ AclDdlService::create()->createTable(new AddressContactTable()); Now the table exists, but we must still make the table definition accessible through the DIC, so the ACL component can set up appropriate repositories. This is achieved through a tag in the service definition: -```php +```PHP $services->set('b2b_address.contact_acl_table', Shopware\B2B\Address\Framework\AddressContactAclTable::class) ->tag('b2b_acl.table'); ``` Finally, we need to register the service in the DIC. This is done by this PHP snippet: -```php +```PHP $services->set('b2b_address.acl_repository', Shopware\B2B\Acl\Framework\AclRepository::class) ->factory([service('b2b_acl.repository_factory'), 'createRepository']) ->args(['s_user_addresses']); @@ -365,7 +365,7 @@ other contexts than *contact* and *role*. For this, you have to create a differe An `AclContextResolver` is responsible for extracting the primary key out of a given context object and produces a query that joins the main ACL table. This is done by implementing `getQuery`, `isMainContext`, and `extractId`. -```php +```PHP getNextPrefix(); @@ -414,7 +414,7 @@ Notice the `getMainPrefix` call. This allows the ACL component to be joined with An implementation of extract id usually looks like this: -```php +```PHP public function extractId($context): int { if ($context instanceof ContactIdentity) { diff --git a/products/extensions/b2b-suite/guides/core/overload-classes.md b/products/extensions/b2b-suite/guides/core/overload-classes.md index a0802e53a6..4f784e51ce 100644 --- a/products/extensions/b2b-suite/guides/core/overload-classes.md +++ b/products/extensions/b2b-suite/guides/core/overload-classes.md @@ -17,7 +17,7 @@ To add new functionality or overload existing classes to change functionality, t In the release package, our services.php looks like this: -```php +```PHP // /src/Resources/config/services.php /src/Resources/config/services.php /src/Resources/config/services.php set('my.controller', My\Namespace\MyApiController::class); $services->set('my.api_route_provider', My\Namespace\DependencyInjection\MyApiRouteProvider::class) @@ -91,7 +91,7 @@ Refer to this linked documentation to learn more about placeholders and placehol If you want to use parameters, you have to define an order in which the parameters should be passed to the action: -```php +```PHP [ 'GET', // the HTTP method '/my/hello/{name}', // the sub-route will be concatenated to http://my-shop.de/api/b2b/my/hello/world @@ -103,7 +103,7 @@ If you want to use parameters, you have to define an order in which the paramete And now, you can use the placeholders value as a parameter: -```php +```PHP /src/Resources/config/services.php Date: Tue, 3 Mar 2026 13:44:16 +0100 Subject: [PATCH 6/7] fix: cs fix reviewdog languagetool --- .../checkout/document/add-custom-document-type.md | 2 +- .../plugins/checkout/payment/add-payment-plugin.md | 14 +++++++------- .../checkout/payment/customize-payment-provider.md | 2 +- .../content/cms/add-data-to-cms-elements.md | 2 +- .../plugins/content/mail/add-data-to-mails.md | 4 ++-- .../data-handling/add-custom-complex-data.md | 2 +- .../framework/store-api/add-store-api-route.md | 2 +- .../plugin-fundamentals/add-custom-service.md | 6 +++--- .../plugin-fundamentals/add-scheduled-task.md | 2 +- .../plugin-fundamentals/dependency-injection.md | 2 +- .../plugin-fundamentals/listening-to-events.md | 2 +- guides/plugins/plugins/redis.md | 6 +++--- .../plugins/storefront/add-custom-controller.md | 6 +++--- .../plugins/plugins/storefront/add-custom-page.md | 4 ++-- .../plugins/storefront/add-custom-twig-function.md | 2 +- .../add-dynamic-content-via-ajax-calls.md | 4 ++-- .../development/adding-component.md | 2 +- .../development/extending-migration.md | 2 +- 18 files changed, 33 insertions(+), 33 deletions(-) diff --git a/guides/plugins/plugins/checkout/document/add-custom-document-type.md b/guides/plugins/plugins/checkout/document/add-custom-document-type.md index 01956676f9..f448d64bf1 100644 --- a/guides/plugins/plugins/checkout/document/add-custom-document-type.md +++ b/guides/plugins/plugins/checkout/document/add-custom-document-type.md @@ -368,7 +368,7 @@ Now we need to register our custom `ExampleDocumentRenderer` in the service cont ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/services.php] +```PHP [PLUGIN_ROOT/src/Resources/config/services.php] /src/Resources/config/services.php] +```PHP [/src/Resources/config/services.php] /src/Resources/config/` location. Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. +The last thing we need to do now is to tell Shopware how to look for new routes in our plugin. This is done with a `routes.php` file at `/src/Resources/config/` location. Take a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. ```PHP // /src/Resources/config/routes.php diff --git a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md b/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md index 05089b96bc..18d6e30608 100644 --- a/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md +++ b/guides/plugins/plugins/plugin-fundamentals/add-custom-service.md @@ -23,7 +23,7 @@ Place a file with name `services.php` into a directory called `src/Resources/con ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/services.php] +```PHP [PLUGIN_ROOT/src/Resources/config/services.php] set(MyCustomService::class) ->args([ service(Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider::class), @@ -43,7 +43,7 @@ Once you've set up your Redis connections as explained in the [Redis configurat 2. Use `Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider` as factory to define custom services: - ```php + ```PHP $services->set('my.custom.redis_connection', \Redis::class) ->factory([service(Shopware\Core\Framework\Adapter\Redis\RedisConnectionProvider::class), 'getConnection']) ->args(['%myservice.redis_connection_name%']); @@ -70,7 +70,7 @@ Once you've set up your Redis connections as explained in the [Redis configurat 3. Inject connection directly by name: - ```php + ```PHP $services->set(MyCustomService::class) ->args([service('shopware.redis.connection.connection_name')]); ``` diff --git a/guides/plugins/plugins/storefront/add-custom-controller.md b/guides/plugins/plugins/storefront/add-custom-controller.md index 4b4ed1f6d3..7ed39df617 100644 --- a/guides/plugins/plugins/storefront/add-custom-controller.md +++ b/guides/plugins/plugins/storefront/add-custom-controller.md @@ -141,7 +141,7 @@ Next, we need to register our controller in the DI-container and make it public. ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/services.php] +```PHP [PLUGIN_ROOT/src/Resources/config/services.php] /src/Resources/config/` location. -Have a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. +Take a look at the official [Symfony documentation](https://symfony.com/doc/current/routing.html) about routes and how they are registered. ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/routes.php] +```PHP [PLUGIN_ROOT/src/Resources/config/routes.php] set(ExamplePageLoader::class) ->public() ->args([ @@ -205,7 +205,7 @@ In addition, it is necessary to pass the argument with the ID of the `ExamplePag ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/services.php] +```PHP [PLUGIN_ROOT/src/Resources/config/services.php] set(SwagCreateMd5Hash::class) ->public() ->tag('twig.extension'); // Required diff --git a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md index fac666c864..ccf2259b3b 100644 --- a/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md +++ b/guides/plugins/plugins/storefront/add-dynamic-content-via-ajax-calls.md @@ -58,7 +58,7 @@ The following `services.php` and `routes.php` are identical as in the before men ::: code-group -```php [PLUGIN_ROOT/src/Resources/config/services.php] +```PHP [PLUGIN_ROOT/src/Resources/config/services.php] set(Shopware\Commercial\B2B\B2BSuiteMigration\Components\EmployeeManagement\EmployeeManagementMigrationConfigurator::class) ->tag('b2b.migration.configurator', ['priority' => 9000]); ``` diff --git a/products/extensions/b2b-suite-migration/development/extending-migration.md b/products/extensions/b2b-suite-migration/development/extending-migration.md index 3b8e14d007..00071d1284 100644 --- a/products/extensions/b2b-suite-migration/development/extending-migration.md +++ b/products/extensions/b2b-suite-migration/development/extending-migration.md @@ -18,7 +18,7 @@ This section explains how to add new fields to an existing entity or introduce n **Example**: - ```php + ```PHP $services->set(MigrationExtension\B2BMigration\B2BExtensionMigrationConfigurator::class) ->tag('b2b.migration.configurator.extension'); ``` From f57f243f2d95f5fb417f32e3a54ff90abcfdb825 Mon Sep 17 00:00:00 2001 From: umut Date: Tue, 3 Mar 2026 14:33:30 +0100 Subject: [PATCH 7/7] chore: update service definition examples in migration-assistant --- .../creating-a-new-migration-profile.md | 94 ++++++++++--------- ...-shopware-migration-assistant-converter.md | 29 +++--- .../extending-the-migration-connector.md | 38 ++++---- 3 files changed, 81 insertions(+), 80 deletions(-) diff --git a/products/extensions/migration-assistant/guides/creating-a-new-migration-profile.md b/products/extensions/migration-assistant/guides/creating-a-new-migration-profile.md index fb21732efe..3d5634a935 100644 --- a/products/extensions/migration-assistant/guides/creating-a-new-migration-profile.md +++ b/products/extensions/migration-assistant/guides/creating-a-new-migration-profile.md @@ -13,7 +13,7 @@ If you want to migrate your data from a different source system than Shopware, c First, it is required that you already have installed the [Migration Assistant](https://github.com/shopware/SwagMigrationAssistant) plugin in Shopware 6 and have created a demo source system database with a `product` table. To create the table, use this SQL statement: -```sql +```SQL CREATE TABLE product ( id int PRIMARY KEY NOT NULL AUTO_INCREMENT, @@ -31,7 +31,7 @@ This table should simulate a simple third-party source system, which should be m In the first step, you have to create a new profile for your source system: -```php +```PHP - - +```PHP +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\OwnProfile::class) + ->tag('shopware.migration.profile'); ``` ## Creating a gateway Next, you have to create a new gateway which supports your profile: -```php +```PHP - - - - +```PHP +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; + +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\Gateway\OwnLocaleGateway::class) + ->args([ + service(SwagMigrationAssistant\Migration\Gateway\Reader\ReaderRegistry::class), + service(SwagMigrationAssistant\Profile\Shopware\Gateway\Connection\ConnectionFactory::class), + ]) + ->tag('shopware.migration.gateway'); ``` ## Creating a credentials page If you want to try your current progress in the Administration, you can select the profile and gateway in the migration wizard. If you try to go to the next page, there will be an error message because no credentials page was found. To create a new credentials page, you have to add an `index.js` for your new component into `Resources/app/administration/src/own-profile/profile`: -```javascript +```JAVASCRIPT import { Component } from 'src/core/shopware'; import template from './swag-migration-profile-ownProfile-local-credential-form.html.twig'; @@ -296,7 +298,7 @@ Component.register('swag-migration-profile-ownProfile-local-credential-form', { As you can see above, currently, the template does not exist and you have to create this file: `swag-migration-profile-ownProfile-local-credential-form.html.twig` -```html +```HTML {% block own_profile_page_credentials %}
@@ -374,7 +376,7 @@ Note that the component name isn't random and consists of: To see your credentials page, you have to register this component in your `main.js`: -```javascript +```JAVASCRIPT import './own-profile/profile'; ``` @@ -382,7 +384,7 @@ import './own-profile/profile'; Now the credential page is loaded in the Administration and the connection check will succeed. But there is no data selection if you open the data selection table. To add an entry to this table, you have to create a `ProductDataSet` first: -```php +```PHP - - +```PHP +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\DataSelection\ProductDataSelection::class) + ->tag('shopware.migration.data_selection'); - - - +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\DataSelection\DataSet\ProductDataSet::class) + ->tag('shopware.migration.data_set'); ``` ## Creating a product gateway reader Currently, you can see the `DataSelection` in the Administration, but if you select it and start a migration, no product will be migrated. That is because the gateway `read` function isn't implemented yet. But before you can implement this function, you have to create a new `ProductReader` first: -```php +```PHP - - - +```PHP +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\Gateway\Reader\ProductReader::class) + ->parent(SwagMigrationAssistant\Profile\Shopware\Gateway\Local\Reader\AbstractReader::class) + ->args([ + service(SwagMigrationAssistant\Profile\Shopware\Gateway\Connection\ConnectionFactory::class), + ]) + ->tag('shopware.migration.reader'); ``` Once the `ProductReader` is created and registered, you can use it in the `read` method of the `OwnLocaleGateway`: -```php +```PHP - - - - +```PHP +$services->set(SwagMigrationOwnProfileExample\Profile\OwnProfile\Converter\ProductConverter::class) + ->args([ + service(SwagMigrationAssistant\Migration\Mapping\MappingService::class), + service(SwagMigrationAssistant\Migration\Logging\LoggingService::class), + ]) + ->tag('shopware.migration.converter'); ``` To write new entities, you have to create a new writer class, but for the product entity, you can use the `ProductWriter`: -```php +```PHP - - - - - +In the end, you have to register your decorated converter in your `services.php`: + +```PHP +$services->set(SwagMigrationExtendConverterExample\Profile\Shopware\Converter\Shopware55DecoratedProductConverter::class) + ->decorate(SwagMigrationAssistant\Profile\Shopware55\Converter\Shopware55ProductConverter::class) + ->args([ + service('.inner'), + service(SwagMigrationAssistant\Migration\Mapping\MappingService::class), + service(SwagMigrationAssistant\Migration\Logging\LoggingService::class), + service(SwagMigrationAssistant\Migration\Media\MediaFileService::class), + ]); ``` With this, you have decorated your first Shopware migration converter. diff --git a/products/extensions/migration-assistant/guides/extending-the-migration-connector.md b/products/extensions/migration-assistant/guides/extending-the-migration-connector.md index 82b058b40f..1aa283fbc3 100644 --- a/products/extensions/migration-assistant/guides/extending-the-migration-connector.md +++ b/products/extensions/migration-assistant/guides/extending-the-migration-connector.md @@ -19,7 +19,7 @@ With this setup, you have the bundle plugin in Shopware 5 and also the bundle pl To fetch your data via the Shopware 5 API, you have to create a bundle repository first: -```php +```PHP +```PHP +$services->set('swag_migration_bundle_api_example.bundle_repository', SwagMigrationBundleApiExample\Repository\BundleRepository::class) + ->parent(SwagMigrationConnector\Repository\AbstractRepository::class); ``` ## Creating bundle service In the next step, you create a new `BundleService`, which uses your new `BundleRepository` to fetch all bundles and products to map them to one result array: -```php +```PHP @@ -143,19 +141,20 @@ class BundleService extends AbstractApiService } ``` -You have to register the `BundleService` in your `service.xml`: +You have to register the `BundleService` in your `services.php`: -```html - - - +```PHP +$services->set('swag_migration_bundle_api_example.bundle_service', SwagMigrationBundleApiExample\Service\BundleService::class) + ->args([ + service('swag_migration_bundle_api_example.bundle_repository'), + ]); ``` ## Create a new API controller At last, you have to create a new API controller, which uses the `BundleService` to get your bundle data: -```php +```PHP @@ -186,7 +185,7 @@ class Shopware_Controllers_Api_SwagMigrationBundles extends Shopware_Controllers Now you have to create the `BundleReader` in the [SwagMigrationBundleExample](extending-a-shopware-migration-profile) plugin, which only contains the Shopware 5 API route: -```php +```PHP - - +```PHP +$services->set(SwagMigrationBundleExample\Profile\Shopware\Gateway\Api\BundleReader::class) + ->parent(SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\ApiReader::class) + ->tag('shopware.migration.reader'); ``` With that, you have implemented your first plugin migration via API.