- The
userentity is now write protected via api. To create, update or delete auserentity, you need theuser-verifiedoauth-scope. The scope can be requested over the/api/oauth/tokenroute.$client->request('POST', '/api/oauth/token', [ 'grant_type' => 'password', 'client_id' => 'administration', 'username' => 'admin', 'password' => 'shopware', 'scope' => ['user-verified'], ]);
-
The usage of
entityin theshopware.entity.definitiontag is deprecated and will be removed with 6.4.- Therefore change:
<tag name="shopware.entity.definition" entity="product"/>To:<tag name="shopware.entity.definition"/> - As a fallback, this function is used first
- Therefore change:
-
We deprecated the
LongTextWithHtmlFieldin 6.2, useLongTextFieldwithAllowHtmlflag instead -
The Mailer is not overwritten anymore, instead the swiftmailer.transport is decorated.
- Therefore the MailerFactory returns a Swift_Transport Instance instead of Swift_Mailer
- The MailerFactory::create Method is deprecated now
Before:
new LongTextWithHtmlField('content', 'content')After:
(new LongTextField('content', 'content'))->addFlags(new AllowHtml() -
CartBehavior::isRecalculation is deprecated and will be removed in version 6.3
-
Please use context permissions instead:
- Permissions can be configured in the SalesChannelContext.
CartBehavioris created based on the permissions fromSalesChannelContext, you can check the permissions at this class.- Permissions exists:
ProductCartProcessor::ALLOW_PRODUCT_PRICE_OVERWRITESProductCartProcessor::SKIP_PRODUCT_RECALCULATIONDeliveryProcessor::SKIP_DELIVERY_RECALCULATIONPromotionCollector::SKIP_PROMOTION - Define permissions for AdminOrders at class
SalesChannelProxyControllerwithin the array constantADMIN_ORDER_PERMISSIONS. - Define permissions for the Recalculation at class
OrderConverterwithin the array constantADMIN_EDIT_ORDER_PERMISSIONS. - Extended permissions with subscribe event
SalesChannelContextPermissionsChangedEvent, see detail at classSalesChannelContextFactory
-
The usage of
$connection->executeQuery()for write operations is deprecated, use$connection->executeUpdate()instead. -
For the possibility to add individual product to across selling, you need to use a new field for creating a cross selling
- Please use type
productListorproductStreamin order to create a corresponding cross selling
- Please use type
-
The
\Shopware\Core\Framework\DataAbstractionLayer\EntityExtensionInterfacewill be removed, extend from the abstract class\Shopware\Core\Framework\DataAbstractionLayer\EntityExtensioninstead. -
Deprecated
\Shopware\Core\Framework\Routing\RouteScopeInterfaceuse abstract class\Shopware\Core\Framework\Routing\AbstractRouteScopeinstead -
Deprecated
\Shopware\Core\Content\ContactForm\ContactFormServiceuse the new service\Shopware\Core\Content\ContactForm\SalesChannel\ContactFormRouteinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingGatewayuse\Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingRouteInterfaceinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingGatewayInterfaceuse\Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingRouteInterfaceinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchGatewayuse\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchRouteInterfaceinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchGatewayInterfaceuse\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchRouteInterfaceinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Suggest\ProductSuggestGatewayInterfaceuse\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchRouteInterfaceinstead -
Deprecated
\Shopware\Core\Content\Product\SalesChannel\Suggest\ProductSuggestGatewayuse\Shopware\Core\Content\Product\SalesChannel\Search\ProductSearchRouteInterfaceinstead -
Deprecated
\Shopware\Core\Checkout\Customer\SalesChannel\AccountServiceuse one of the following new services\Shopware\Core\Checkout\Customer\SalesChannel\ChangeCustomerProfileRoute\Shopware\Core\Checkout\Customer\SalesChannel\ChangeEmailRoute\Shopware\Core\Checkout\Customer\SalesChannel\ChangePasswordRoute\Shopware\Core\Checkout\Customer\SalesChannel\ChangePaymentMethodRoute\Shopware\Core\Checkout\Customer\SalesChannel\LoginRoute\Shopware\Core\Checkout\Customer\SalesChannel\LogoutRoute\Shopware\Core\Checkout\Customer\SalesChannel\SendPasswordRecoveryMailRoute\Shopware\Core\Checkout\Customer\SalesChannel\ResetPasswordRoute
-
Deprecated
\Shopware\Core\Content\Newsletter\NewsletterSubscriptionServiceInterfaceand\Shopware\Core\Content\Newsletter\NewsletterSubscriptionServiceuse one of the following new services\Shopware\Core\Content\Newsletter\SalesChannel\NewsletterSubscribeRoute\Shopware\Core\Content\Newsletter\SalesChannel\NewsletterUnsubscribeRoute\Shopware\Core\Content\Newsletter\SalesChannel\NewsletterConfirmRoute
-
Deprecated
\Shopware\Core\Checkout\Customer\SalesChannel\AccountRegistrationServiceuse one of the following new services\Shopware\Core\Checkout\Customer\SalesChannel\RegisterRouteInterface\Shopware\Core\Checkout\Customer\SalesChannel\RegisterConfirmRouteInterface
-
Deprecated
\Shopware\Core\Checkout\Promotion\Cart\Discount\DiscountPackagerInterfaceuse\Shopware\Core\Checkout\Promotion\Cart\Discount\DiscountPackagerinstead -
Added optional second parameter
$contextto\Shopware\Core\Framework\Plugin\PluginManagementService::uploadPluginand\Shopware\Core\Framework\Plugin\PluginManagementService::deletePlugin. It will be required in 6.3.0 -
Deprecated
\Shopware\Core\Framework\Plugin\PluginManagementService::extractPluginZipwhich will be private in 6.3.0 -
Added optional third parameter
$definitiontoShopware\Elasticsearch\Framework\ElasticsearchHelper::addTerm. It will be required in 6.3.0. -
Added a new translatable
labelproperty to\Shopware\Core\Content\ImportExport\ImportExportProfileDefinition- This property is required
- The name may be omitted now
-
Added new message
\Shopware\Core\Framework\Adapter\Cache\Message\CleanupOldCacheFoldersto cleanup old cache folders invar/cache
-
sw-settings-custom-field-set- Removed method which overrides the mixin method
getList, use the computedlistingCriteriainstead - Add computed property
listingCriteria
- Removed method which overrides the mixin method
-
sw-settings-document-list- Removed method which overrides the mixin method
getList, use the computedlistingCriteriainstead - Add computed property
listingCriteria
- Removed method which overrides the mixin method
-
Refactor
sw-settings-snippet-list- Removed
StateDeprecated - Remove computed property
snippetSetStore, use `snippetSetRepository' instead - Add computed property
snippetSetRepository - Add computed property
snippetSetCriteria
- Removed
-
Refactor
sw-settings-snippet-set-list- Remove
StateDeprecated - Remove computed property
snippetSetStore, use `snippetSetRepository' instead - Add computed property
snippetSetCriteria - The method
onConfirmCloneis now an asynchronous method
- Remove
-
Refactor mixin
sw-settings-list.mixin- Remove
StateDeprecated - Remove computed property
store, useentityRepositoryinstead - Add computed property
entityRepository - Add computed property
listingCriteria
- Remove
-
The component sw-plugin-box was refactored to use the "repositoryFactory" instead of "StateDeprecated" to fetch and save data - removed "StateDeprecated" - removed computed "pluginStore" use "pluginRepository" instead
-
The component sw-settings-payment-detail was refactored to use the "repositoryFactory" instead of "StateDeprecated" to fetch and save data
- removed "StateDeprecated"
- removed computed "paymentMethodStore" use "paymentMethodRepository" instead
- removed computed "ruleStore" use "ruleRepository" instead
- removed computed "mediaStore" use "mediaRepository" instead
-
Refactor the module
sw-settings-number-range-detail- Remove LocalStore
- Remove StateDeprecated
- Remove data typeCriteria
- Remove data numberRangeSalesChannelsStore
- Remove data numberRangeSalesChannels
- Remove data numberRangeSalesChannelsAssoc
- Remove data salesChannelsTypeCriteria
- Remove computed numberRangeStore use numberRangeRepository instead
- Remove computed firstSalesChannel
- Remove computed salesChannelAssociationStore
- Remove computed numberRangeStateStore use numberRangeStateRepository instead
- Remove computed salesChannelStore use salesChannelRepository instead
- Remove computed numberRangeTypeStore use numberRangeTypeRepository instead
- Remove method onChange
- Remove method showOption
- Remove method getPossibleSalesChannels
- Remove method setSalesChannelCriteria
- Remove method enrichAssocStores
- Remove method onChangeSalesChannel
- Remove method configHasSaleschannel
- Remove method selectHasSaleschannel
- Remove method undeleteSaleschannel
-
Refactored
sw-newsletter-recipient-list- Removed LocalStore
- Removed StateDeprecated
- Removed Computed salesChannelStore, use salesChannelRepository instead
- Removed Computed tagStore, use tagRepository instead
- Removed Computed tagAssociationStore
-
Refactored mapErrorService
- Deprecated
mapApiErrors, usemapPropertyErrors - Added
mapCollectionPropertyErrorsto mapErrorService for Entity Collections
- Deprecated
-
Deprecated
sw-multi-ip-selectwith version 6.4, use thesw-multi-tag-ip-select-component instead -
Replaced Store based datahandling with repository based datahandling in media specific components and modules, including the following changes
- sw-media-field is deprecated and replaced by sw-media-field-v2
- Added injection of
repositoryFactory - Replaced computed property
mediaStorewithmediaRepository - Method
fetchItemis now async - Method
fetchSuggestionsis now async
- Added injection of
- sw-media-list-selection is deprecated and replaced by sw-media-list-selection-v2
- Added injection of
repositoryFactory - Added injection of
mediaService - Replaced computed property
mediaStorewithmediaRepository - Method
onUploadsAddedis now async - Method
successfulUploadis now async
- Added injection of
- sw-media-preview is deprecated and replaced by sw-media-preview-v2
- Added injection of
repositoryFactory - Replaced computed property
mediaStorewithmediaRepository - Method
fetchSourceIfNecessaryis now async - Method
getDataUrlFromFileis now async
- Added injection of
- sw-media-upload is deprecated and replaced sw-media-upload-v2
- Added injection of
repositoryFactory - Added injection of
mediaService - Replaced computed property
defaultFolderStorewithdefaultFolderRepository - Watcher of prop
defaultFolderis now async - Method
createdComponentis now async - Method
onUrlUploadis now async - Method
handleUploadis now async - Method
getDefaultFolderIdis now async - Replaced method
handleUploadStoreEventwithhandleMediaServiceUploadEvent
- Added injection of
- sw-duplicated-media is deprecated and replaced sw-duplicated-media-v2
- Added injection of
repositoryFactory - Replaced computed property
mediaStorewithmediaRepository - Replaced method
handleUploadStoreEventwithhandleMediaServiceUploadEvent - Method
updatePreviewDatais now async - Method
renameFileis now async - Method
skipFileis now async - Method
replaceFileis now async
- Added injection of
- sw-media-modal is deprecated and replaced by sw-media-modal-v2
- Added injection of
repositoryFactory - Added injection of
mediaService - Replaced computed property
mediaStorewithmediaRepository - Replaced computed property
mediaFolderStorewithmediaFolderRepository - Method
fetchCurrentFolderis now async - Method
onUploadsAddedis now async - Method
onUploadsFinishedis now async
- Added injection of
- sw-upload-store-listener is deprecated and replaced by sw-upload-listener
- Added injection of
repositoryFactory - Added injection of
mediaService - Added computed property
mediaRepository - Method
handleErroris now async
- Added injection of
- sw-media-compact-upload is deprecated and replaced by sw-media-compact-upload-v2
- sw-media-field is deprecated and replaced by sw-media-field-v2
-
Deprecated method
getFields, usegetStructuredFieldsinstead -
Removed module
sw-settings-newsletter-configand componentsw-settings-newsletter-config -
Refactored settings items list
-
Deprecated
sw_settings_content_card_slot_pluginstwig block with version 6.4 -
If your Plugin extends
src/module/sw-settings/page/sw-settings-index/sw-settings-index.html.twigto appear in the "plugins" tab on settings page, remove the extension from your plugin and add ansettingsItemArray to your Module instead:Module.register('my-awesome-plugin') { // ... settingsItem: [ { name: 'my-awesome-plugin', // unique name to: 'my.awesome.plugin.index', // dot notated route to your plugin's settings index page label: 'my.awesome.plugin.title', // translation snippet key group: 'plugins', // register plugin under "plugins" tab in settings page icon: 'use a shopware icon here', // OR component: 'component' // use a component here, if you want to render the icon in any other way } // ... more settings items ] }
-
-
Implemented the possibility to add individual product to cross selling
- Added
sw-product-cross-selling-assignmentcomponent
- Added
-
CustomFields are now sorted naturally when custom position is used with customFieldPosition (for example 1,9,10 instead of 1,10,9)
-
The id of checkbox and switch fields are now unique. Therefore you have to update your selectors if you want to get the fields by id. This was an important change, because every checkbox and switch field has the same id. This causes problems when you click on the corresponding label.
-
Added block
sw_sales_channel_detail_analytics_fields_anonymize_iptosw-sales-channel-detail-analytics.html.twig
- We removed the SCSS skin import
@import 'skin/shopware/base'inside/Users/tberge/www/sw6/platform/src/Storefront/Resources/app/storefront/src/scss/base.scss.-
If you don't use the
@Storefrontbundle in yourtheme.jsonand you are importing the shopware corebase.scssmanually you have to import the shopware skin too in order to get the same result:Before
@import "../../../../vendor/shopware/platform/src/Storefront/Resources/app/storefront/src/scss/base.scss";
After
@import "../../../../vendor/shopware/platform/src/Storefront/Resources/app/storefront/src/scss/base.scss"; @import "../../../../vendor/shopware/platform/src/Storefront/Resources/app/storefront/src/scss/skin/shopware/base";
-
- We changed the storefront ESLint rule
comma-dangletonever, so that trailing commas won't be forcefully added anymore - The theme manager supports now tabs. Usage:
"config": {
"tabs": {
"colors": {
"label": {
"en-GB": "Colours",
"de-DE": "Farben"
}
},
},
"blocks": {
...
},
...,
"fields": {
"sw-color-brand-primary": {
"label": {
"en-GB": "Primary colour",
"de-DE": "Primärfarbe"
},
"type": "color",
"value": "#008490",
"editable": true,
"block": "themeColors",
"tab": "colors",
"order": 100
},
...
}
}When you don´t specify a tab then it will be shown in the main tab.
- Added Twig Filter
replace_recursivefor editing values in nested Arrays. This allows for editing js options in Twig:
{% set productSliderOptions = {
productboxMinWidth: sliderConfig.elMinWidth.value ? sliderConfig.elMinWidth.value : '',
slider: {
gutter: 30,
autoplayButtonOutput: false,
nav: false,
mouseDrag: false,
controls: sliderConfig.navigation.value ? true : false,
autoplay: sliderConfig.rotate.value ? true : false
}
} %}
{% block element_product_slider_slider %}
<div class="base-slider"
data-product-slider="true"
data-product-slider-options="{{ productSliderOptions|json_encode }}">
</div>
{% endblock %}Now the variable can be overwritten with replace_recursive:
{% block element_product_slider_slider %}
{% set productSliderOptions = productSliderOptions|replace_recursive({
slider: {
mouseDrag: true
}
}) %}
{{ parent() }}
{% endblock %}-
Added basic captcha support to the storefront
- Routes annotated with
@Captchawill now require all active captchas to be valid - Captchas may be registered using the
shopware.storefront.captchatag and need to extend theAbstractCaptchaclass
- Routes annotated with
-
Added
HoneypotCaptcha- This captcha checks wether a form field hidden from the user was filled out and stops the request if that's the case
- The
HoneypotCaptchais active by default
-
If you use the
widgets.search.pageletroute in your template, you have to replace this withwidgets.search.pagelet.v2:- Before:
url('widgets.search.pagelet', { search: page.searchTerm }) - After:
url('widgets.search.pagelet.v2')
- Before:
-
It is no longer possible to send requests against the
sales-channel-apiwith theHttpClient. You have to use theStoreApiClientfor this:- before:
import Plugin from 'src/plugin-system/plugin.class'; import HttpClient from 'src/service/http-client.service'; export default class MyStorefrontPlugin extends Plugin { init() { this.client = new HttpClient(); this.client.get('sales-channel-api-route', response => {}) } }
- after:
import Plugin from 'src/plugin-system/plugin.class'; import StoreApiClient from 'src/service/store-api-client.service'; export default class MyStorefrontPlugin extends Plugin { init() { this.client = new StoreApiClient(); this.client.get('sales-channel-api-route', response => {}); } }
- before:
-
Added block
component_head_analytics_tag_configtoanalytics.html.twig
With 6.2 we have refactored the implementation of the indexers. We had to make this decision because of two problems:
- the indexers were interdependent so that they always had to be executed one after the other and never in parallel.
- many indexers were not designed to be triggered by message queue and therefore ran into mysql deadlocks or indexed wrong data.
This now has the following consequences:
- all indexers in the shopware core have been marked as deprecated and will be removed in 6.3. Accordingly, new indexers have been implemented.
- if you have called the indexers, please use the new indexers. The old indexers are still available in the system, but without source code.
- if you have implemented your own indexer, you have to adapt it to the new system - as described below.
- if you are using DAL fields, which were previously filled automatically by an indexer, you will now have to write your own indexer - we have provided classes for this purpose. The following DAL fields are affected:
4.1
\Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToManyIdField4.2\Shopware\Core\Framework\DataAbstractionLayer\Field\TreeLevelField4.3\Shopware\Core\Framework\DataAbstractionLayer\Field\TreePathField4.4\Shopware\Core\Framework\DataAbstractionLayer\Field\ChildCountField
The new indexers work as follows:
- each indexer extends abstract
Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexer - each indexer takes care of indexing a whole entity
- if several data on an entity need to be indexed, a single indexer takes care of the successive updating of the data
- an event is thrown at the end of the indexer so that plugins can subscribe to the event to index additional data for this entity
The base Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexer class looks as follows:
abstract class EntityIndexer
{
/**
* Returns a unique name for this indexer. This function is used for core updates
* if a indexer has to run after an update.
*/
abstract public function getName(): string;
/**
* Called when a full entity index is required. This function should generate a list of message for all records which
* are indexed by this indexer.
*/
abstract public function iterate($offset): ?EntityIndexingMessage;
/**
* Called when entities are updated over the DAL. This function should react to the provided entity written events
* and generate a list of messages which has to be processed by the `handle` function over the message queue workers.
*/
abstract public function update(EntityWrittenContainerEvent $event): ?EntityIndexingMessage;
/**
* Called over the message queue workers. The messages are the generated messages
* of the `self::iterate` or `self::update` functions.
*/
abstract public function handle(EntityIndexingMessage $message): void;
}The iterate and update functions are intended to trigger indexing. The iterate is triggered on a full index and the update when an entity is written in the system.
In both cases, an EntityIndexingMessage can be returned which is then either handled by the message queue or directly.
The following ProductIndexer is intended to illustrate once again how such an indexer works. This indexer can be used as a template. Only the entity that is handled must be exchanged here.
<?php declare(strict_types=1);
namespace Shopware\Core\Content\Product\DataAbstractionLayer;
use Shopware\Core\Content\Product\Events\ProductIndexerEvent;
use Shopware\Core\Content\Product\ProductDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Dbal\Common\IteratorFactory;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexer;
use Shopware\Core\Framework\DataAbstractionLayer\Indexing\EntityIndexingMessage;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
class ProductIndexer extends EntityIndexer
{
/** @var IteratorFactory */
private $iteratorFactory;
/** @var EntityRepositoryInterface */
private $repository;
/** @var EventDispatcherInterface */
private $eventDispatcher;
public function getName(): string
{
return 'product.indexer';
}
public function iterate($offset): ?EntityIndexingMessage
{
$iterator = $this->iteratorFactory->createIterator($this->repository->getDefinition(), $offset);
$ids = $iterator->fetch();
// loop end? return null
if (empty($ids)) {
return null;
}
return new EntityIndexingMessage($ids, $iterator->getOffset());
}
public function update(EntityWrittenContainerEvent $event): ?EntityIndexingMessage
{
$updates = $event->getPrimaryKeys(ProductDefinition::ENTITY_NAME);
if (empty($updates)) {
return null;
}
// update essential data immediately - one example can be the available stock of an product
return new EntityIndexingMessage($updates, null, $event->getContext());
}
public function handle(EntityIndexingMessage $message): void
{
$ids = $message->getData();
if (empty($ids)) {
return;
}
// update all required data
$this->eventDispatcher->dispatch(new ProductIndexerEvent($ids, $message->getContext()));
}
}In case you have used fields from the DAL, which filled automatically by an indexer, you have now to trigger the data indexing for this fields by yourself. We provide updater classes which you call from your indexer. However, we have adapted the previous indexers so that they will continue to update your entities automatically during the 6.2 version. If you have started the indexing process yourself, you can set a flag to prevent the old indexing process from working for your entity.
-
\Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToManyIdField- Can be updated by
\Shopware\Core\Framework\DataAbstractionLayer\Indexing\ManyToManyIdFieldUpdater - Old indexing can be disabled by
public function hasManyToManyIdFields(): bool { return false; }in your entity definition
- Can be updated by
-
\Shopware\Core\Framework\DataAbstractionLayer\Field\TreeLevelFieldand\Shopware\Core\Framework\DataAbstractionLayer\Field\TreePathField- can be updated by
\Shopware\Core\Framework\DataAbstractionLayer\Indexing\TreeUpdater - Old indexing can be disabled by
public function isTreeAware(): bool { return false; }in your entity definition
- can be updated by
-
\Shopware\Core\Framework\DataAbstractionLayer\Field\ChildCountField- can be updated by
\Shopware\Core\Framework\DataAbstractionLayer\Indexing\ChildCountUpdater - Old indexing can be disabled by
public function isChildCountAware(): bool { return false; }in your entity definition
- can be updated by
Simply create an indexer as above, inject the service and call it when your entity is updated.
If you have implemented your own seo urls in the system, you will have to initiate the indexing of these urls yourself in the future. For the 6.2 version we have implemented a flag which defines whether the old indexing process should continue to work.
To update the seo urls correctly you need an indexer which indexes the entity behind the seo url. If there is already an indexer for the entity in the core you can register yourself on the indexer event, otherwise you have to write your own indexer.
In the indexer you can use the \Shopware\Core\Content\Seo\SeoUrlUpdater service to generate the seo urls. Here is an example how to call it:
<?php declare(strict_types=1);
namespace Shopware\Storefront\Framework\Seo\SeoUrlRoute;
use Shopware\Core\Content\Product\Events\ProductIndexerEvent;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Content\Seo\SeoUrlUpdater;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class SeoUrlUpdateListener implements EventSubscriberInterface
{
/**
* @var SeoUrlUpdater
*/
private $seoUrlUpdater;
public function __construct(SeoUrlUpdater $seoUrlUpdater)
{
$this->seoUrlUpdater = $seoUrlUpdater;
}
public static function getSubscribedEvents()
{
return [
ProductEvents::PRODUCT_INDEXER_EVENT => 'updateProductUrls',
];
}
public function updateProductUrls(ProductIndexerEvent $event): void
{
$this->seoUrlUpdater->update('frontend.detail.page', $event->getIds());
}
}To disable the old indexing process for a seo url route you have to set the flag \Shopware\Core\Content\Seo\SeoUrlRoute\SeoUrlRouteConfig::$supportsNewIndexer. This is easily done in the getConfig method of your SeoUrlRoute class.
public function getConfig(): SeoUrlRouteConfig
{
return new SeoUrlRouteConfig(
$this->productDefinition,
self::ROUTE_NAME,
self::DEFAULT_TEMPLATE,
true,
true // disable old indexing
);
}Since the new indexers are now designed to be processed in parallel via the message queue, MySQL deadlocks can quickly occur when the same table is written by different processes. For this we have provided the helper class \Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery.
This offers various possibilities to avoid a MySQL deadlock:
$query = new RetryableQuery(
$this->connection->prepare('UPDATE product SET active = :active WHERE id = :id')
);
$query->execute(['id' => $id, 'active' => 1]);
$query = $this->connection->createQueryBuilder();
$query->update('...');
RetryableQuery::executeBuilder($query);
RetryableQuery::retryable(function() {
$this->connection->executeUpdate('...');
});