When an end user has taken an action in any application it's a good idea to provide the user feedback on that action. So for example if the save product button has been clicked in Magento 2 you would expect to see something like this:
If you are writing custom code for Magento it is fairly straight forward to add your own messages to be displayed to the user. Usually you would do this in your own controller code - the context object provides you with access to the \Magento\Framework\Message\ManagerInterface
via $context->getMessageManager()
as the framework provided means to do so.
Out of the box the following messages can be used:
$this->messageManager->addSuccessMessage(__('All good'));
$this->messageManager->addNoticeMessage(__('Something you should be aware of is ....'));
$this->messageManager->addWarningMessage(__('This is not so good....'));
$this->messageManager->addErrorMessage(__('This is bad'));
which will then render to the user as:
This is usually all you need in user interaction.
However sometimes you need that little bit more from those messages, for example you might want to include an URL directly in the message itself. Your first inclination probably looks similar to mine and you end up doing:
$this->messageManager->addNoticeMessage(__('Before we can start please configure something <a href="https://example.com">here</a>'));
but we soon find out that all output gets automatically escaped:
Luckily for us there is an inbuilt solution for us to use custom messages. In the \Magento\Framework\Message\ManagerInterface
there is an extra set of methods which all include Complex in their name:
/* @see \Magento\Framework\Message\ManagerInterface */
public function addComplexSuccessMessage($identifier, array $data = [], $group = null);
public function addComplexErrorMessage($identifier, array $data = [], $group = null);
public function addComplexWarningMessage($identifier, array $data = [], $group = null);
public function addComplexNoticeMessage($identifier, array $data = [], $group = null);
To make use of them we first need to set up our identifier via some di.xml
instructions:
<!-- etc/adminhtml/di.xml-->
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\View\Element\Message\MessageConfigurationsPool">
<arguments>
<argument name="configurationsMap" xsi:type="array">
<item name="foomanExample" xsi:type="array">
<item name="renderer" xsi:type="const">\Magento\Framework\View\Element\Message\Renderer\BlockRenderer::CODE</item>
<item name="data" xsi:type="array">
<item name="template" xsi:type="string">Fooman_Example::messages/foomanExample.phtml</item>
</item>
</item>
</argument>
</arguments>
</type>
</config>
The template file could then look like this
/* view/adminhtml/templates/messages/foomanExample.phtml */
<a href="<?php echo $block->escapeUrl($block->getData('url'))?>"><?php echo $block->escapeHtml(__('click here first')) ?></a>
and last but not least we need to invoke this message and pass in the url information as part of the data array:
$this->messageManager->addComplexNoticeMessage(
'foomanExample',
[
'url' => $this->_helper->getUrl('to/our/route')
]
);
And we have our intended end result:
As a quick reminder do not output user input without properly sanitizing the input and escaping the output. The various $block->escapeX
methods like $block->escapeHtml()
and $block->escapeUrl()
are your friends.