Migrating dimension config [v9]
Neos 9.x Content
This is content for the upcoming Neos 9.0 release with the rewritten Content Repository based on Event Sourcing.
We heavily work on these docs right now, so expect rough edges.
Dimensions are configured in Settings.yaml, but are also reflected in the content repository - thus in the database.
As a consequence, if you change dimension configuration in Settings.yaml you need to run some node migrations to adjust the content repository. On this page, we explain the different cases and how to run them:
- adding a dimension
- e.g. site without dimensions => site with a
language
dimension - e.g. site with one dimension
language
=> site with dimensionslanguage, market
- e.g. site without dimensions => site with a
- adding a dimension value
- e.g. site with
language:en
dimension value => site withlanguage:en,de
dimension values
- e.g. site with
- adding a dimension value as fallback
- e.g. site with
language:de
dimension value => site withlanguage:de,ch
dimension values; wherede
is the fallback ofch
- e.g. site with
- renaming dimensions / dimension values
- removing dimensions / dimension values
#General process
Adjusting dimension configuration of a running site works in two steps:
- Make sure your users do not have unpublished changes
- adjust dimension configuration in Settings.yaml at key
Neos.ContentRepositoryRegistry.contentRepositories.default.contentDimensions
(or analogous for other content repositories) - described on page Content Repository Configuration. - Also adjust the Site Dimension Routing configuration in Settings.yaml at key
Neos.Neos.sites.*.contentDimensions.resolver
- described in the Routing docs. - run node migrations migrations (through CLI commands) to apply your configuration changes to the content in your content repository
- flush the cache and test to ensure the updated routing configuration is active.
#Adding a dimension
Adjust dimension configuration
In Settings.yaml
you need to add the market
dimension configuration.
Neos:
ContentRepositoryRegistry:
contentRepositories:
default:
contentDimensions:
'language':
label: 'Language'
values:
'en':
label: English
'de':
label: German
# Newly added:
'market':
label: 'Market'
value:
'b2b':
label: B2B
'b2c':
label: B2C
Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver
- described in the Routing docs, to configure how the dimension should be mapped to URLs.
Running dimension migrations
When switching from no dimensions to 1 dimension; or from 1 dimension to two dimensions, you need to move all existing DimensionSpacePoints, because they need the additional "axis" defined.
Moving needs to be done for all existing DimensionSpacePoints, because a 1-dimensional DimensionSpacePoint is not reachable if you have two dimensions configured.
Please also check the references for node migration.
# Example: No Dimensions => 1 Dimension
# Source: no dimensions
# Target: a "language" dimension, where the already existing content should appear as "en"
comments: 'Move all nodes without dimension values to language "en"'
migration:
-
transformations:
-
type: 'MoveDimensionSpacePoint'
settings:
from: { }
to: { language: 'en' }
# Example: 1 Dimension => 2 Dimensions (additional market dimension)
# For every existing dimension value in "language", move it to the "b2c" market.
comments: 'Move all nodes into their market dimension'
migration:
-
transformations:
-
type: 'MoveDimensionSpacePoint'
settings:
from: { language: 'en' }
to: { language: 'en', market: 'b2c' }
-
type: 'MoveDimensionSpacePoint'
settings:
from: { language: 'de' }
to: { language: 'de', market: 'b2c' }
The root node is, by definition, existing in every DimensionSpacePoint. Thus, if you change dimension configuration, the root node(s) need to be updated as well. The following migration creates empty root node aggregate dimensions for each allowed dimension combination and removes them for all non-configured ones. You can create a dedicated migration file or just append it as additonal transformation to your dimension migration.
comments: 'Synchronize root node aggregates with content repository configuration'
migration:
-
transformations:
-
type: 'UpdateRootNodeAggregateDimensions'
settings:
nodeType : 'Neos.Neos:Sites'
Adjust the root node dimensions
If you want to move any content into a new dimension space point, you need to do that first, before you update the root node aggregate dimensions.
# Run the node migration to apply the changes to the dimension values
./flow nodemigration:execute 20240924093814 # Move dimension values
./flow nodemigration:execute 20240924095647 # Update root aggregate dimensions
Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:
./flow flow:cache:flush
#Adding a dimension value
Adjust dimension configuration
In Settings.yaml
you need to add the new value for the existing content dimension.
Neos:
ContentRepositoryRegistry:
contentRepositories:
default:
contentDimensions:
'language':
label: 'Language'
values:
'en':
label: English
'de':
label: German
# Newly added:
'fr':
label: French
Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver
- described in the Routing docs, to configure how the dimension should be mapped to URLs.
Running dimension migrations
The root node is, by definition, existing in every DimensionSpacePoint. Thus, if you change dimension configuration, the root node(s) need to be updated as well. The following migration creates empty root node aggregate dimensions for each allowed dimension combination and removes them for all non-configured ones.
Please also check the references for node migration.
comments: 'Synchronize root node aggregates with content repository configuration'
migration:
-
transformations:
-
type: 'UpdateRootNodeAggregateDimensions'
settings:
nodeType : 'Neos.Neos:Sites'
Adjust the root node dimensions
If you want to move any content into a new dimension space point, you need to do that first, before you update the root node aggregate dimensions.
# Run the node migration to apply the changes to the dimension values
./flow nodemigration:execute 20240924095647 # Update root aggregate dimensions
Optional: Copy content from existing dimension
You can translate - as usual - in the Neos backend, by using the dimension switcher. Sometimes, however, it is useful to pre-populate content from an existing dimension. This can be done via the ./flow content:createVariantsRecursively
command as shown below:
# copy all content from "en" to "fr"
./flow content:createVariantsRecursively '{"language": "en"}' '{"language": "fr"}'
In case you need this, you could also add the dimension value as a fallback. The difference is:
- When not using fallbacks and copying content, the content is disconnected from the original dimension value. If a node in one dimension changes, it does not in the other.
- When using fallbacks (see below), then a change on the base dimension (e.g.
de
) will be automatically visible in the specialized dimension (e.g.ch
), as long as no specific content has been created for the specialization (e.g.ch
).
Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:
./flow flow:cache:flush
#Adding a dimension value as fallback
Adjust dimension configuration
In Settings.yaml
you need to add the new value for the existing content dimension, underneath specializations
of the parent dimension value:
Neos:
ContentRepositoryRegistry:
contentRepositories:
default:
contentDimensions:
'language':
label: 'Language'
values:
'en':
label: English
'de':
label: German
# Newly added:
specializations:
'ch':
label: Swiss
Also adjust the Site Dimension Routing configuration in Settings.yaml at key Neos.Neos.sites.*.contentDimensions.resolver
- described in the Routing docs, to configure how the dimension should be mapped to URLs.
Running dimension migrations
Dimension shine through in the event-sourced content repository is implemented on the write side. This means that dimension fallbacks are resolved when writing changes. While reading, dimension fallbacks do not matter.
This is why you need to migrate the content to add a dimension shine-through; possible through a node migration like the following.
Please also check the references for node migration.
comments: 'Add shine through from german to swiss german'
migration:
-
transformations:
-
type: 'AddDimensionShineThrough'
settings:
from: { language: 'de' }
to: { language: 'ch' }
In this scenario it's not necessary to update the root node aggregated dimension space points.
# Run the node migration to apply the shine through
./flow nodemigration:execute 20240814180321
Finally, flush the cache, to ensure no cached routes or cached rendered pages still exist. Then, test your changes:
./flow flow:cache:flush