Neos 9 Beta-10 Release

Today we released another Neos 9 Beta.

It contains many bugfixes, big refactoring and great new features.

Thanks to all who contributed <3 And for the great discussions in slack.

Upgrade instructions from Beta 8 / Beta 9

previous beta → Neos 9 Beta-8 Release

In your composer.json you should require 9.0.0-beta10 for all Neos packages from the development distribution and for the NeosUi as well as Flow:

"neos/flow": "9.0.0-beta10",
"neos/neos": "9.0.0-beta10",
"neos/neos-ui": "9.0.0-beta10"

The database can be migrated via the commands:

./flow cr:setup
./flow cr:projectionreplay --projection contentGraph

Also due to the use of modern JSON features maria-db 10.4 is no longer supported see issue.


!!! 1.) :sparkles: Highlight :sparkles: Make read model workspace aware

Getting a subgraph

The WorkspaceName must be passed along to get a subgraph instead of the internal ContentStreamId:

- $subgraph = $contentRepository->getContentGraph()->getSubgraph(
-     $workspace->currentContentStreamId,
-     $dimensionSpacePoint,
-     VisibilityConstraints::withoutRestrictions()
- );              
+ $subgraph = $contentRepository->getContentGraph($workspace->workspaceName)->getSubgraph(
+     $dimensionSpacePoint,
+     VisibilityConstraints::withoutRestrictions()
+ );

Deprecation of field Node::$contentSubgraphIdentity (removal with next beta)

The ContentSubgraphIdentity was intermediate part of the node’s “Read Model” identity.
It was deprecated. Please use Node::$contentRepositoryId, Node::$workspaceName, Node::$dimensionSpacePoint, and Node::$aggregateId instead,
or see NodeAddress::fromNode() for passing the identity around.
The visibility-constraints now reside in Node::$visibilityConstraints.
There is no replacement for the previously attached content-stream-id. Please refactor the code to use the newly available workspace-name.

!!! 2.) Introduce new FlowQuery operations; Rename or remove Node fields like node.nodeType

Deprecation of Node::getLabel() (removal with next beta)

To get the label for a Node in PHP, one must replace Node::getLabel() with a call to Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface::getLabel:

+ #[Flow\Inject]
+ protected NodeLabelGeneratorInterface $nodeLabelGenerator;
+ $this->nodeLabelGenerator->getLabel($node);
- $node->getLabel();

For Fusion please use the new FlowQuery operation:

- ${node.label}
+ ${q(node).label()}

Rename of field Node::$nodeAggregateId (old syntax removal with next beta)

In php Node::nodeAggregateId was renamed to Node::aggregateId.
(The previous way will be removed with the next beta)

- ${node.nodeAggregateId.value}
- ${node.identifier}
+ ${q(node).id()}

Deprecation of field Node::$nodeType (removal with next beta)

In php Node::nodeType can be considered removed. Please use NodeTypeManager::getNodeType instead:

- $node->nodeType;
+ $contentRepository = $this->contentRepositoryRegistry->get($node->contentRepositoryId);
+ $nodeType = $contentRepository->getNodeTypeManager()->getNodeType($node->nodeTypeName);

The use in Fusion is discouraged (tip use a custom EEL Helper), but you can access it like:

- ${node.nodeType}
+ ${Neos.Node.getNodeType(node)}

Rename of field Node::$nodeName (old syntax removal with next beta)

In php Node::nodeName was renamed to Node::name.

The use in Fusion is discouraged (tip use a custom EEL Helper), but you can access it like:


!!! 3.) :sparkles: Performance, synchronous cr instead of async + complexity

Currently, we use Scripts::executeCommandAsync() (using the SubprocessProjectionCatchUpTrigger) to trigger catch ups.
This can lead to many sub requests if there are a lot of commands (e.g. multiple editors creating content simultaneously).

Apart from the eminent performance issue this can bring, those sub requests might be killed if the parent request ends (or due to process limits).

We will be switching to a synchronous catch-up mechanism in the next beta.
That basically means that ContentRepository::handle() will always be blocking until all projections are up to date.

Deprecation of CommandResult::block (removal with next beta)

The CommandResult::block calls must be removed as the backwards compatibility layer will be removed with next beta.

- $contentRepository->handle($command)->block();
+ $contentRepository->handle($command);

!!! 4.) Rename ‘internal’ property _hiddenInIndex to hiddenInMenu

Following Fusion prototypes no longer accept an renderHiddenInIndex option but only consider renderHiddenInMenu. In the case you overwrote the default behaviour for any of these prototypes you should rename the option to renderHiddenInMenu.

Affected: Neos.Neos:BreadcrumbMenu, Neos.Neos:BreadcrumbMenuItems, Neos.Neos:DimensionsMenu, Neos.Neos:DimensionsMenuItems, Neos.Neos:Menu, Neos.Neos:MenuItems.

Accessing the property has to be adjusted as well.

upgrade from 8.3

- $node->isHiddenInIndex();
+ $node->getProperty('hiddenInMenu');

upgrade from 9.x-dev

- $node->getProperty('_hiddenInIndex');
+ $node->getProperty('hiddenInMenu');

5.) :sparkles: Neos Ui Publishing and conflict resolution :sparkles:

The PublishDiscardDialog is a modal that is supposed to pop up whenever an editor starts publishing or discarding their workspace.

This change introduces a dialog workflow that allows users to select a resolution strategy for dealing with conflicts that arise during the synchronization of their user workspace.

!!! 6.) Flow ViewInterface and Fusion View adjustments

  • !!! FEATURE: ViewInterface returns PSR StreamInterface

    • the views are now independent of the ControllerContext
      • ViewInterface::setControllerContext is not part of the interface anymore and will only be called on demand
    • the ActionRequest if necessary can be accessed via the variable “request” (like “settings”)
    • ViewInterface::canRender was required for fallbackviews which have been removed long ago, and so this artefact will be removed as well.
    • !!! the return type is now forced to be either a ResponseInterface or a StreamInterface. Simple strings must be wrapped in a psr stream! (see StreamFactoryTrait::createStream)
  • !!! FEATURE: Render ResponseInterface directly in Fusion Views

To streamline the behaviour and fix these specialities, the FusionView will return if applicable a ResponseInterface and for simple (string) cases a psr StreamInterface. Both cases have to be anticipated on call site.
The change is not expected to be super breaking if a StreamInterface will be returned as for classes with loose typing this will be converted via __toString.

Also, the new Fusion globals should be used from a Fusion object to access the request:

- $this->runtime->getControllerContext()->getRequest();
+ $possibleRequest = $this->runtime->fusionGlobals->get('request');
+ if (!$possibleRequest instanceof ActionRequest) {
+     // ... fallback
+ }

If you use the Fusion Runtime directly, which is internal, you should know that using Runtime::render as entry point will fail to render Neos.Neos:Plugin, Neos.Fusion.Form and also lead to weird behaviour when rendering a Neos.Fusion:Http.Message.
The Fusion view should be used for interacting with Fusion, but if you must, you can leverage Runtime::renderEntryPathWithContext to render a full page with all special cases.

7.) Content repository stability improvements

The method ContentGraphInterface::findChildNodeAggregateByName now returns a single NodeAggregate, if any and has been renamed:

- $contentGraph->findChildNodeAggregatesByName(...);
+ $contentGraph->findChildNodeAggregateByName(...);

8.) DX improvements for the new content repository


Neos Content Repository

Neos Ui


Dev only relevant

List of things


Neos Ui