Contao 6 no longer encodes user input. Instead, values are stored in their raw form in the database. This means you must ensure that all output is properly encoded. The easiest way to do this is by using Twig templates.
If you send content directly to the browser or return HTML from a hook, callback, or event listener without using Twig
templates, use StringUtil::specialchars() or htmlspecialchars() to encode it.
If user input contains HTML, use the sanitize_html('contao') Twig filter or the contao.html_sanitizer service to
sanitize it.
In Twig templates, make sure that anything you output using |raw does not contain untrusted data. If you are not
absolutely sure, replace |raw with |sanitize_html('contao').
Because input encoding is no longer used, the decodeEntities and useRawRequestData options have been removed. All
values are now stored decoded, using the raw data from the request.
You can still enable HTML sanitization by setting allowHtml to true. For fields with rte set, HTML sanitization
is enabled automatically. You can disable it by setting preserveTags to true.
Double encoding is now enabled by default in all core methods. If you need to escape a value without double encoding,
pass false as the third argument to StringUtil::specialchars().
Double encoding has also been reenabled in Twig. The Contao escaper strategy, as well as the contao_html and
contao_html_attr escape filters, which previously prevented double encoding, have been removed.
Contao 6 no longer supports .html5 templates. Use Twig templates instead.
The Twig filter |insert_tag_raw has been renamed to |insert_tag_html. The old name is deprecated. The new filter
expects pre-escaped input, so if you previously used something like foo|insert_tag_raw|raw, you need to change the
order to foo|raw|insert_tag_html now.
However, using |raw is generally discouraged. Use foo|sanitize_html('contao')|insert_tag_html instead.
The @Contao_Global Twig namespace has been renamed to @Contao_User. If you reference the namespace explicitly, update your template and controller references accordingly.
In almost all cases, you do not need to reference this namespace explicitly. Instead, use the managed @Contao namespace.
The remaining Symfony bundle templates have been removed. Use the corresponding Contao templates instead:
@ContaoCore/Error/layout.html.twig→@Contao/error/_layout.html.twig@ContaoCore/Image/Studio/_macros.html.twig→@Contao/component/_figure.html.twig@ContaoCore/Image/Studio/figure.html.twig→@Contao/component/_figure.html.twig@ContaoCore/blank.html.twig→ no replacement (empty template)
The contao.image.studio.figure_renderer service and the figure insert tag now render the generic component/_figure template by default.
Changing a password in the frontend with the "personal data" module is no longer possible. Use the "change password" module instead.
The tl_member.language field no longer contains country codes. If you need locale codes with regions, such as
de_AT, you can restore the previous behavior by using a custom callback:
#AsCallback('tl_member', target: 'fields.language.options')Use the label_callback instead.
String values returned by the label_callback are now HTML-encoded. If you need to return HTML, return a
Contao\CoreBundle\DataContainer\RecordLabel object with htmlLabel set.
BBCode support in the comments bundle has been removed. Existing comments are migrated to plain text format.
Model values are now automatically cast to the correct type. An exception is thrown if a value cannot be converted.
$contentModel->id = '123'; // Cast to integer
$contentModel->id = 'not_an_int'; // Throws an exceptionMissing values in models now return their default value instead of null.
Frontend form widgets no longer implement the Widget::generate() method. Use Widget::parse() instead.
The TRBL widget has been removed. Use the text widget with 'size' => 4' or the row wizard instead.
It is no longer possible to have multiple backend themes. Use the contao.backend.custom_css and
contao.backend.custom_js configuration options to customize the backend instead.
The BackendUser class no longer generates the back end navigation. The getUserNavigation hook is still
supported but has been deprecated. Use the KnpMenu events instead.
Headers sent via header() are no longer merged into the final Symfony response. Work with the Symfony Response
object instead.
The priority marker interfaces HighPriorityMessageInterface, NormalPriorityMessageInterface, and
LowPriorityMessageInterface have been dropped. Use the AsMessage attribute instead:
#[AsMessage('contao_prio_high|contao_prio_normal|contao_prio_low')]The database-assisted filesystem (DBAFS) now uses a 128-bit xxHash as its default hashing algorithm. Make sure the
database and filesystem are in sync before upgrading, for example, by running contao:filesync. Existing md5 hashes
will be removed from the database during a migration and rebuilt the first time the filesystem is synchronized.
The following JavaScript backwards compatibility layers have been removed. Use the corresponding Stimulus attributes instead:
Backend.enableToggleSelect→data-contao--check-all-target="input"Theme.setupCtrlClick→data-contao--deeplink-target="primary"Backend.initScrollOffsetandBackend.getScrollOffset→data-contao--scroll-offset-target="scrollTo"
Use the contao--toggle-fieldset Stimulus controller instead of AjaxRequest.toggleFieldset:
data-controller="contao--toggle-fieldset" data-contao--toggle-fieldset-id-value="your_value" data-contao--toggle-fieldset-table-value="your_table" data-contao--toggle-fieldset-collapsed-class="collapsed"Use the contao--textarea-autogrow Stimulus controller instead of Theme.setupTextareaResizing.
Use the contao--toggle-receiver and contao--toggle-sender Stimulus controllers instead of Theme.setupMenuToggle,
Theme.setupProfileToggle, and Theme.setupSplitButtonToggle.
All remaining Theme.* methods have been removed.
TinyMCE has been replaced by HugeRTE, either update your custom be_tinyMCE.* templates
accordingly or require the TinyMCE contao component yourself.