Releases: shopware/shopware
Release v6.7.8.2
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
Critical Fixes
Webhook for order state change
Fixed an undefined array key warning within the webhook handling, which could lead to a server error, if strict error displaying is set up.
Digital product legacy states repair after update
We fixed a bug in the indexer for the product.states field, which lead to issues where rules (and flows depending on those rules) with the line item with product state condition did not work as expected. This especially affected the flows to deliver digital download products after purchase.
This release repairs digital products with missing legacy states via a one-time UpdatePostFinishEvent subscriber.
The repair runs automatically once per installation and is marked as completed in app_config.
What's Changed
- fix: disable anonymous tracking (backport: 6.7.8.x) by Soner (@shyim) in #15527
- fix: Missing undefined array key checks in HookableBusinessEvent (backport: 6.7.8.x) by Michael Telgmann (@mitelg) in #15518
- feat: add webhook failure strategy (backport: 6.7.8.x) by Aydin Hassan (@AydinHassan) in #15546
- fix: price inheritance is not applied correctly for product variants (backport: 6.7.8.x) by YTN (@nguyenytran) in #15548
- fix: digital products are not downloadable on storefront (backport: 6.7.8.x) by Vin Le (@vienthuong) in #15614
Full Changelog: v6.7.8.1...v6.7.8.2
Get in touch
Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)
Security Release v6.6.10.15
Security Release v6.7.8.1
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
Critical Fixes
Double signature verification in app-reregistration flow
Introduces a secure, asynchronous app secret rotation feature to the app system, including both API and CLI interfaces.
Added a new API endpoint and command for rotating app secrets, implemented the underlying rotation logic, and adjusted the app registration process to support secret updates and dual signature confirmation.
This increases security by enforcing a two-step verification process during app re-registration, ensuring that only authorized parties can update app secrets.
LoginRoute and AccountService don't throw CustomerNotFoundException
The LoginRoute and AccountService have been updated to no longer throw a CustomerNotFoundException when a login attempt is made with an email address that does not exist in the system.
Instead, they will now throw a generic BadCredentialsException without revealing whether the email address is registered or not.
This change enhances security by preventing potential attackers from enumerating valid email addresses through error messages.
Improve OrderRoute deepLinkCode filter type validation
Improve the logic in \Shopware\Core\Checkout\Order\SalesChannel\OrderRoute::load to ensure the deepLinkCode filter is an instance of \Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter.
What's Changed
- GHSA-c4p7-rwrg-pf6p - Double signature verification in app-reregistration flow
- GHSA-gqc5-xv7m-gcjq - Limit account enumeration via Store API
- GHSA-7vvp-j573-5584 - Proper check for the deepLinkCode filter type
Full Changelog: v6.7.8.0...v6.7.8.1
Get in touch
Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)
Release v6.6.10.14
See the UPGRADE.md for all important technical changes.
- #13348 - Online cancelation request (Elektronische Widerrufsfunktion)
- #15308 - fix: allow searching while suggest is still loading
- #14854 - e-invoice xml file is not sent as an email attachment
- #15307 - ES working wrong with NotEquals filter in nested fields
- #14838 - Administration: Button label says “Create and download PDF” but downloads ZUGFeRD XML (filename null.xml)
- #15258 - feat: Add event for the config info API route (backport: 6.6.x)
- #12229 - Shop version 6.7.2.0 + Commercial version 7.1.2 = 500 error
- #14904 - Regression: database:refresh-migration Command no longer works
- #15206 - fix: Reading associations via the parent, if the parent has multiple associations of the same type and to the same entity (backport: 6.6.x)
- #14555 - "Promotion -> All -> Are None of" fails to match
- #13812 - Variant preselection in category product listing doesn’t work in Shopware 6.7.x
- #14922 - Major update of DomPDF dependency
- #14613 - fix: Profiler: use $title as key in start() so it will correctly be unset in stop() (backport: 6.6.x)
- #14951 - fix: add branch alias for main (backport: 6.6.x)
- #14647 - Cart line item is missing regulation price
- #14017 - Accessibility Inputs do not have autocomplete attribute
- #14024 - Accessibility: User account contains some level A issues
- #3478 - App flow actions custom headers in async mode 6.6.x backport #14678
Release v6.7.8.0
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
Features
New internal comment for state machine state history entries
A new internal comment field was added to the state change modal which can be used to add additional information about a state change.
The internal comment is only visible in the administration and not shown to customers.
It can be found in the state machine state history modal (state change modal) on the detail page of an order.
API
Core
Indexing the product's custom fields
Custom fields used in product sorting and product streams, as well as those belonging to apps, are now included when indexing products with Elasticsearch.
Deprecation of increment-based message queue statistics
The increment-based message queue statistics system is deprecated and will be removed in v6.8.0.0.
What's changing:
- The Administration notification center will no longer show indexing progress notifications (e.g., "X products will be indexed")
- API endpoint
GET /api/_info/queue.jsonis deprecated - useGET /api/_info/message-stats.jsoninstead
Deprecated configuration options:
shopware.admin_worker.enable_queue_stats_workershopware.increment.message_queue
Deprecated code:
IncrementGatewayRegistry::MESSAGE_QUEUE_POOLconstant- Increment-based handling in
MessageQueueStatsSubscriber::onMessageHandled()
Why?
The increment-based statistics were often inaccurate due to hardcoded multipliers and missing decrements in edge cases. The replacement functionality was introduced in #8698
Immediate disable:
To disable the deprecated functionality before v6.8.0.0:
shopware:
admin_worker:
enable_queue_stats_worker: falseInternal product streams
A new boolean field internal has been added to product streams with a default value of false.
This allows you to mark product streams as internal for system or plugin use, preventing them from appearing in merchant-facing selection lists throughout the Administration (e.g., in categories, cross-selling, CMS elements, or sales channels).
Use this feature when you need to create product streams programmatically that should not be modified or selected by shop administrators.
Database table helper class
A new helper class \Shopware\Core\Framework\Util\Database\TableHelper was introduced,
which could be used to check the table for existence, columns, indexes, and foreign keys.
Deprecation of helper methods in \Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper
As consequence of the introduction of the new table helper class following methods are deprecated and will be removed with the next major version:
- \Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper::columnExists
- \Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper::columnIsNullable
- \Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper::tableExists
Migration generator improvements
The migration generator previously used a fixed format: fk.<table-name>.<column> for foreign key names.
Doctrine does not support this format and creates broken migrations; therefore, we changed to the format fk__<table-name>__<column> for foreign key names.
Also, the generator now sets CASCADE DELETE on foreign keys for the translation table references.
CategoryIndexer selective indexing optimization
The CategoryIndexer now skips tree/child-count updaters when parentId hasn't changed, and breadcrumb updater when name hasn't changed. All updaters still run for INSERT and DELETE operations.
Updated doctrine/dbal dependency
The doctrine/dbal dependency was updated to the new 4.4 minor version.
They introduced many deprecations, especially in the SchemaManager tool, which also might affect you.
Read more about it in their upgrade guide.
Primary key validation in dal:validate command
The dal:validate command now includes validation to detect mismatches between database PRIMARY KEY constraints and entity definition PrimaryKey flags.
This validation prevents silent failures where queries return correct total counts but empty data arrays due to entity hydration failures caused by inconsistent primary key definitions.
When a mismatch is detected, the command provides a clear error message indicating which fields differ between the database schema and the entity definition.
Deprecation of default value for serializer in #[Serialized] field attribute
When you use #[Serialized] field in your attribute entity you should always pass the serializer explicitly, as the default serializer does not work as expected.
Additionally, the SerializerField will become internal in the next major release, as that field should be only used for attribute entities, but never directly in classic EntityDefinitions.
Administration
Product detail variants: configSettingGroups as computed and deprecations
In sw-product-detail-variants, the following changes were made:
configSettingGroups(now computed): Previously adata()property set byloadConfigSettingGroups(). It is now a computed property derived fromproductEntity.configuratorSettingsandgroups.loadConfigSettingGroups()(deprecated): Marked as@deprecated tag:v6.8.0. It will be removed in 6.8.0 without replacement.
Deprecation of items prop in sw-entity-listing component
The items prop in the sw-entity-listing component has been deprecated and will be removed in v6.8.0.
Please use the dataSource prop instead to align with the parent sw-data-grid component.
Before (deprecated):
<sw-entity-listing
:items="entityList"
:repository="entityRepository"
:columns="columns"
/>After (recommended):
<sw-entity-listing
:data-source="entityList"
:repository="entityRepository"
:columns="columns"
/>The component will continue to work with the items prop for backward compatibility, but you will see a deprecation warning in the browser console.
Notification translations now update when language changes
Notifications now store translation keys directly in their title and message fields instead of translating them immediately.
The template checks if the text is a translation key and translates it reactively, allowing notifications to update automatically when the user changes the interface language.
Help text support for color picker custom fields
The color picker type for custom fields now supports adding a help text. When creating or editing a custom field of type "Colorpicker" in Settings > Content > Custom fields, you can now specify a help text that will be displayed to users in the Administration.
sw-select-base clearable button default behavior changed
The showClearableButton prop in sw-select-base now defaults based on the required attribute:
- When
requiredisfalseor not set: clearable button is shown by default - When
requiredistrue: clearable button is hidden by default
Previously, the clearable button was always hidden by default (showClearableButton: false).
Migration: If you relied on the previous behavior where the clearable button was hidden by default, explicitly set :show-clearable-button="false" on your select components.
Storefront
Selling and packaging information in the product detail page
- Display the selling and packaging information with the product that has advanced pricing.
- Deprecated block
buy_widget_price_unitand it childrens inResources/views/storefront/component/buy-widget/buy-widget-price.html.twig, will be moved intoResources/views/storefront/component/buy-widget/buy-widget.html.twig.
Default theme breakpoints now available in theme config
The default layout breakpoints in the Storefront were hard-coded before and couldn't easily be overriden. Now you will find new theme config fields in the default config, which serve as the default values. The fields are hidden in the visual configuration, so they serve as a feature for theme developers for now. You can override the following config fields in your custom theme.json file to change the default breakpoints. The fields are mapped to the existing hard-coded configuration. The configuration is only passed in Twig and JS currently and there is no direct usage in SCSS, as they represent the Bootstrap default breakpoints. If you want to make a full override, you can simply configure the Bootstrap breakpoints in your custom SCSS and use the theme config values for that.
sw-breakpoint-xssw-breakpoint-smsw-breakpoint-mdsw-breakpoint-lgsw-breakpoint-xlsw-breakpoint-xxl
Make static alerts announced in the screenreader
Static alert boxes that are rendered in the DOM on page load were previously not read out by screenreaders.
The role="alert" did not have an effect. Only role="alerts" added to the DOM by JavaScript were read out.
To solve the screenreader issue with static alerts, we introduced a new parameter announceOnLoad.
When announceOnLoad is set to true, the alert box content will be announced in the screenreader right after the page is loaded.
The alert box will apply an additional JavaScript plugin that attempts to trigger the screenreader.
This is done by changing the DOM within the aria-live region after a short delay, which tells the screenreader to read it.
{% sw_include '@Storefront/storefront/utilities/alert.html.twig' with {
type: "primary",
content: "An important mess...
Release v6.6.10.13
See the UPGRADE.md for all important technical changes.
Release v6.7.7.1
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
What's Changed
- fix:
getAddressinAddressDetailPageLoader(backport: 6.7.7.x) by @shopware-octo-sts-app-2[bot] in #14736 - fix: elasticsearch requirement in core bundle (backport: 6.7.7.x) by @shopware-octo-sts-app[bot] in #14725
- fix: order edit loading (backport: 6.7.7.x) by @shopware-octo-sts-app[bot] in #14746
Full Changelog: v6.7.7.0...v6.7.7.1
Get in touch
Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)
Release v6.6.10.12
See the UPGRADE.md for all important technical changes.
- #14353 - fix: Remove usage of deprecated PDO constants (backport: 6.6.x) (#14353)
- #14451 - Fix IAP decoding with old OpenSSL versions
- #14413 - fix: keep mail attachments across flow actions (backport: 6.6.x) (#14443)
- #14058 - fix: Never load unfiltered many-to-many (backport: 6.6.x) (#14438)
- #14475 - fix: attribute entities missing with auto configuration (backport: 6.6.x) (#14475)
- #14482 - feat: Update PHPStan and its Symfony plugin (#14482)
- #13968 - Symfony 7.4 Update
- #14289 - fix: allow bulk edit stock with negative value (backport: 6.6.x) (#14392)
- #14485 - fix: ProductListingLoader shows random product variant instead of the main variant - backport 6.6.x (#14485)
- #11733 - fix: Error when inserting tables in custom field (backport: 6.6.x) (#14537)
- #14633 - fix: document footer placement (backport: 6.6.x) (#14633)
Release v6.7.7.0
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
Features
Symfony 7.4 update
All symfony packages have been updated to version 7.4.
Take a look at the Symfony 7.4 release post for more information.
Especially note that Symfony now requires php-redis extension v6.1 or higher: https://github.com/symfony/symfony/blob/7.4/UPGRADE-7.4.md#cache.
If you note compatibility issues with the Redis extension please check the installed version php-redis.
Changed maintenance mode redirect
After maintenance ends, users are now redirected back to the page they were on before maintenance.
Previously, users were always redirected to the shop homepage.
Support of media paths with up to 2046 characters
Previously the maximum length for media paths was limited to 255 characters (due to default StringField limit) while the
database field already supported up to 2046 characters. This limitation has now been lifted and media paths can be up to
2046 characters long.
Configurable Custom Field Searchability
Custom fields are now not searchable by default. To make a custom field searchable, you need to enable the "Include in search" option in the custom field detail modal when creating or updating a custom field in Settings > System > Custom fields. This change helps optimize index storage size and improve search performance, especially for stores with many custom fields.
Important: When enabling searchability for an existing product custom field, you must rebuild the search index or update the products manually to include the custom field data in search results.
Media Model Viewer
From now on you are able to inspect your 3D models directly in the Media module in the Administration. Simply select a model file and you will find an interactive 3D viewer in the Preview collapsable in the item sidebar on the right. This new component is called sw-model-viewer.
API
Improved tagged based cache invalidation
Next routes now support cache tagging, enabling automatic invalidation when relevant entities are written:
/store-api/breadcrumb/{id}/store-api/media/store-api/product/{productId}/find-variant/store-api/product/{productId}/cross-selling
Core
Rework of DAL query generation for nested filters groups
The DAL criteria builder has been adjusted to generate EXISTS subqueries instead of LEFT JOINs for nested filter groups.
Previously, each level of nested filters resulted in an additional LEFT JOIN, even when the join was only required to check for the existence of a related entity subject to some filter.
In complex criteria trees with multiple filters on the same entity, this led to an exponential explosion of joins and significant performance degradation (e.g., the same table being joined multiple times only to evaluate existence conditions).
An example of this is a query such as "find orders that have a line item of type A and one of type B and one of type C".
According to aadr/2020-11-19-dal-join-filter.md, this would look like:
$criteria->addFilter(
new EqualsFilter('lineItems.type', 'product'),
new EqualsFilter('lineItems.type', 'custom'),
new EqualsFilter('lineItems.type', 'other'),
);Previously, the generated query would LEFT JOIN order_line_item multiple times onto order, causing the query to be extremely slow. The new EXISTS checks prevent this, making the query much faster.
Introduce Immutable DAL flag
A new Immutable flag is available for Data Abstraction Layer fields. Fields marked as immutable can be set during entity creation but cannot be updated later. This prevents accidental renames of technical identifiers that other subsystems rely on. Core entities now using the flag include:
custom_field.namecustom_field.typecustom_field_set.name
Trying to update these columns now results in a WriteConstraintViolationException with the message The field foo is immutable and cannot be updated., giving developers clear feedback when attempting to change these values.
If the value is not set in the payload, or the value won't change, no exception is thrown.
Performance Improvement for ProductCategoryDenormalizer
The SQL Query inside the ProductCategoryDenormalizer has been optimized to run faster, especially on large catalogues.
Previously MySql needed to perform a full table scan based on the where condition, now the result set is already limited by indexed columns.
This lead to performance improvements from up to 3s for the query down to less than 1ms on large catalogues (3000%).
Deprecation of product states in favor of the new product type
The product.states field is deprecated and will be removed in the next major release.
A new field product.type was introduced to clearly indicate whether a product is digital or physical, or other types registered by third-party developers.
As part of this change, the following deprecations were made:
- The
order_line_item.statesfield is deprecated in favor oforder_line_item.payload.product_type. \Shopware\Core\Checkout\Cart\LineItem\LineItem::$statesis deprecated in favor of\Shopware\Core\Checkout\Cart\LineItem\LineItem::$payload['productType'].- The
LineItemProductStatesRuleis deprecated in favor of the newLineItemProductTypeRule. - The
StatesUpdaterservice and its related dispatched events (ProductStatesBeforeChangeEvent,ProductStatesChangedEvent) are deprecated. - A new parameter
shopware.product.allowed_typeswas introduced to allow third-party developers to register additional product types. - For more details, please refer to the 2025-11-14-introduce-product-type-and-deprecate-states.md
If you are using the rule LineItemProductStatesRule, product stream filters, or product listing filters that rely on product.states, you should update them to use the new product.type field instead.
If you create digital products using admin api, you should explicitly set the type field to digital when creating new products instead of relying on backend handling.
New RequestParamHelper
Symfony deprecated the "magic" Request::get() method, which was used to retrieve parameters from the request, by checking the attribute, query or request parameter bags.
For easier backward compatibilty we backported the old behaviour in the new RequestParamHelper class, however, it should only be used in explicit cases, where the parameter could be in any of those parameter bags.
The best practice is to check the explicit parameter bag, where you expect the parameter to be.
However, as we have a lot of API routes that support being called by GET and POST methods both, the helper is handy in such cases.
Before:
$parameter = $request->get($parameterName, $default);After:
$parameter = RequestParameterHelper::get($request, $parameterName, $default);To provide full backward compatibility, the helper currently also checks the attribute bag for the parameter first.
However, it should be possible to strictly differentiate between request attributes (which are generally controlled and set by the application itself) and input parameters (which are provided by the client, and based on how they are passed are either part of the query bag or the request bag) in the future.
Therefore the check of the attribute bag is deprecated and will be removed in the next major release.
When you need to get a value from the request attributes, you should use the Request::attributes->get() method directly.
In case you used to set request attributes to override specific parameters, you should instead overwrite the parametes in the query or request parameter bags directly.
The TranslationLoader class is now decoratable
The TranslationLoader class extends from the new AbstractTranslationLoader class and implements the decoratable pattern. This allows third-party developers to decorate the loader to add custom logic when a translation is loaded.
DomainExceptions don't create \RuntimeException anymore
All factory methods for domain exceptions now return specific exception classes instead of creating a generic \RuntimeException.
Changing the type of the thrown exception from \RuntimeException to a specific domain exception is not considered a breaking change, since all Domain Exceptions extend from \RuntimeException.
This means code like this will stay valid:
try {
$this->someService->willThrowDomainException();
} catch (\RuntimeException $e) {
// handle exception
}Additionally all changed factory methods were marked as deprecated, because the \RuntimeException return type will be removed in the next major release.
This affects the following exception factory methods:
DataAbstractionLayerException::cannotBuildAccessor(...)DataAbstractionLayerException::onlyStorageAwareFieldsAsTranslated(...)DataAbstractionLayerException::onlyStorageAwareFieldsInReadCondition(...)DataAbstractionLayerException::primaryKeyNotStorageAware(...)DataAbstractionLayerException::missingTranslatedStorageAwareProperty(...)DataAbstractionLayerException::noTranslationDefinition(...)DataAbstractionLayerException::missingVersionField(...)DataAbstractionLayerException::unexpectedFieldType(...)WebhookException::invalidDataMapping(...)WebhookException::unknownEventDataType(...)
More fine-grained caching control in HttpCacheCookieEvent
A new doNotStore property was added to the HttpCacheCookieEvent to allow fine-grained control over caching behavior.
This new property...
Release v6.7.6.2
System requirements
- tested on PHP
8.2,8.4and8.5 - tested on
MySQL 8andMariaDB 11
What's Changed
- fix: update i18n snippet handling to ensure reactivity on locale message changes (backport: 6.7.6.x) by Jannis Leifeld (@jleifeld) in #14396
- fix: TypeError when _httpCache route attribute contains string (backport: 6.7.6.x) by Andrii Havryliuk (@h1k3r) in #14430
Full Changelog: v6.7.6.0...v6.7.6.2
Get in touch
Discuss about decisions, bugs you might stumble upon, etc in our community discord. See you there ;)