After many months and long projects, here is Roadiz v1.6 which embodies 3 goals for our team:
- ✅ A short-term goal: PHP 8 compatibility
- ✅ a mid-term goal: migrate our development process to headless architecture
- ⚙ a long-term goal, still in progress: keeping on splitting Roadiz logic into independent components to ease up a future transition to Symfony 5 and… v2

Major changes
Roadiz requires php 7.4 minimum
Upgraded dependencies to allow PHP 8.x
- Moved
gelf
monolog handler to packages suggestions
- Upgraded to Monolog 2.x
Migration to lcobucci/jwt
4.0.x
- Rewrote all OpenId authentication listeners and
JwtAccountToken
Migration to monolog 2.x
Migration to Twig 3.*
spaceless
tag has been deleted and must be replaced with apply spaceless
localizeddate
filter has been deleted and must be replaced with format_datetime
localizednumber
filter has been deleted and must be replaced with format_number
localizedcurrency
filter has been deleted and must be replaced with format_currency
truncate
filter has been deleted and must be replaced with u.truncate
wordwrap
filter has been deleted and must be replaced with u.wordwrap
centralTruncate
filter must be renamed to central_truncate
cache
tag has been removed
New Markdown node-type field options
allow_h2: true
allow_h3: true
allow_h4: true
allow_h5: true
allow_h6: true
allow_bold: true
allow_italic: true
allow_blockquote: true
allow_image: false
allow_list: true
allow_nbsp: true
allow_return: true
allow_link: true
allow_hr: true
allow_preview: true
DotEnv configuration
Roadiz can handle .env
variables inside your app/conf/config.yml
. We are using the same syntax as Symfony in order to get rid of config.yml
shared volume on production and allow Roadiz to be used as a Kubernetes Pod.
Here is an example of Roadiz configuration using dot-env:
appNamespace: my_website
timezone: Europe/Paris
doctrine:
driver: pdo_mysql
host: '%env(string:MYSQL_HOST)%'
user: '%env(string:MYSQL_USER)%'
password: '%env(string:MYSQL_PASSWORD)%'
dbname: '%env(string:MYSQL_USER)%'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
inheritance:
type: single_table
themes:
-
classname: \Themes\MyTheme\MyThemeApp
hostname: '*'
routePrefix: ''
cacheDriver:
type: apcu
host: null
port: null
security:
secret: '%env(string:APP_SECURITY_SECRET)%'
session_name: my_website_token
session_cookie_secure: '%env(bool:APP_SECURITY_COOKIE_SECURE)%'
mailer:
type: '%env(string:MAILER_TYPE)%'
host: '%env(string:MAILER_HOST)%'
port: '%env(int:MAILER_PORT)%'
encryption: '%env(default::MAILER_ENCRYPTION)%'
username: '%env(string:MAILER_USER)%'
password: '%env(string:MAILER_PASSWORD)%'
assetsProcessing:
driver: gd
defaultQuality: '%env(int:APP_ASSETS_DEFAULT_QUALITY)%'
maxPixelSize: '%env(int:APP_ASSETS_MAX_PIXEL_SIZE)%'
jpegoptimPath: /usr/bin/jpegoptim
pngquantPath: /usr/bin/pngquant
Doctrine migration
This is the last time we dump a manual SQL migration in our changelog… promised!
- Rename groups table to usergroups to comply with MySQL 8 reserved words.
ALTER TABLE user_log_entries CHANGE object_class object_class VARCHAR(191) NOT NULL, CHANGE username username VARCHAR(191) DEFAULT NULL;
RENAME TABLE `groups` TO `usergroups`;
ALTER TABLE groups_roles DROP FOREIGN KEY FK_E79D4963FE54D947;
ALTER TABLE groups_roles ADD CONSTRAINT FK_E79D4963FE54D947 FOREIGN KEY (group_id) REFERENCES usergroups (id);
ALTER TABLE users_groups DROP FOREIGN KEY FK_FF8AB7E0FE54D947;
ALTER TABLE users_groups ADD CONSTRAINT FK_FF8AB7E0FE54D947 FOREIGN KEY (group_id) REFERENCES usergroups (id);
ALTER TABLE usergroups RENAME INDEX uniq_f06d39705e237e06 TO UNIQ_98972EB45E237E06;
…Because we finally added Doctrine Migrations tool for next Roadiz and middleware updates. You'll be able to perform application upgrades with:
bin/roadiz migrations:migrate --allow-no-migration
Only static updates will be migrated with this tool, node-types and node-type fields won't generate any Doctrine Migration because if you create your node-type schema on a production environment this will lead into unsynchronized migrations
table (unless you can commit your file changes from your production server which is non-sense in a Docker environment). We prefer to keep using .json
exports and import. But for any other static databases changes, we invite you to generate migration diffs (filtering ns_
tables):
bin/roadiz migrations:diff --allow-empty-diff --filter-expression="#^(?\!ns_)[^\\s]*\$#"
By default, migration files will be generated in app/migrations
folder unless you specify a namespace. Each registered theme can have its own Migrations/
folder, check at your doctrine migration status to see active namespaces:
bin/roadiz migrations:status
After upgrading Roadiz, Doctrine may complain that one migration is skipped, this is the initialization migration. You can mark it as resolved by adding it to migration table:
# [error] Migration RZ\Roadiz\Migrations\Version20201203004857 skipped during Execution. Reason: "Database has been initialized before Doctrine Migration tool."
# Manually add init migration
bin/roadiz migrations:version --add "RZ\Roadiz\Migrations\Version20201203004857"
Themes are now optional
Roadiz can now route nodes-sources without any theme registered until you setup all your services, routes, … directly into a custom
service-provider registered in your AppKernel.
New request-time preview mode
?_preview=1
will trigger preview any time you need. No more need to use preview.php
entry-point. This may ease up previewing APIs and non-HTML responses.
Of course, security is still enforce if Preview mode is enabled.
BC break: all Roadiz services that depended on Kernel::isPreview()
now depend on PreviewResolverInterface
which allows late-binding and abstracting preview mode logic.
New Roadiz flavor: Headless-edition
- https://github.com/roadiz/headless-edition is a light-weight edition without any theme and already configured with
roadiz/abstract-api-theme
for creating a JAM stack and use whatever frontend framework.
- All business logic can be added in
src
folder, no need to register theme(s), just register your service provider into AppKernel
. Do you see it? We are slowly going to a more standard Symfony app architecture.
- Rezo Zero' TreeWalker is now preconfigured with
AutoChildrenNodeSourceWalker
which reads your node-types configuration to build a data-graph against your children node-types fields.
Abstract Api Theme
roadiz/abstract-api-theme
becomes default Roadiz public endpoint to expose your CMS content as JSON. This a read-only REST API engine which will automatically expose your node-types and will filter them. It uses JSON-LD like syntax and Hydra schema for collections and outputs simple JSON entity for detailled requests. Rezo Zero' TreeWalker is also serialized into detailled requests to be able to build an entire website page using only one API request.
See detailled documentation
Minor changes
SVG are not rendered as object
Not-inlined SVG documents are now rendered as <img>
for a better compatibility with CSS and object-fit
properties.
<img src="/files/folder/file.svg" />
Interfaces and contracts
We are trying to split Roadiz logic into non-dependent modules. In order to acheive this, we need more independent interfaces
to be able to couple loosely components, especially for Entities
relationships. So Roadiz requires now:
Frontend controllers use TranslationInterface
- Many methods switch from
RZ\Roadiz\Core\Entities\Translation
to RZ\Roadiz\Core\AbstractEntities\TranslationInterface
.
- All your theme controllers
indexAction
signatures must comply with TranslationInterface
- Be prepared to keep on this way on next Roadiz releases, we aim at using interfaces whenever possible to decouple CMS entities from your themes.
Refactored form types and validators dependencies
All Roadiz form types were written using $options
as a dependency injector 🤦. We now use constructor to inject services and dependencies into AbstractType
classes thanks to RZ\Roadiz\CMS\Forms\Extension\ContainerFormExtension
.
Same refactoring for every ConstraintValidators thanks to ContainerConstraintValidatorFactory
and Psr11.
This update is introducing some BC breaks with existing setups. But we shall keep on this way to allow Roadiz logic to be split into independent components.
Roadiz back-office will still be rendered with Twig environment but we expect headless-edition to become the main flavor for creating new frontend projects. We will keep maintaining Twig theming but Roadiz' BaseTheme repository won't be updated frequently (on the JS/CSS side) as our team will focus on headless architecture.
Headless-edition will allow more developers and teams to use Roadiz with their favorite front-end framework such as Gatsby or NuxtJS for building API-driven experiences. Even using Netlify-like platforms and static-generated pages.
We hope that this new release will bring Roadiz closer to frontend developers and open up our CMS to many workflows while keeping Roadiz core philosophy: a content-centric approach to building websites.
See you for next release…