typo3typo3-13.x

TYPO3 13 custom validation message


I have a question about validation in Extbase: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Reference/Validation/Index.html

I added a simple NotEmpty validation to my model:

#[Validate([
    'validator' => 'NotEmpty',
    'options' => [
        'nullMessage' => 'Achtung Fehler',
        'emptyMessage' => 'Achtung Fehler',
    ],
])]
protected string $title = '';

In the frontend, I have a simple form. When it is submitted without a title, the following error occurs:

"An error occurred while trying to call Vendor\Extension\Controller\MyController->createAction()" (which I assume comes from the default errorAction)

I thought that you could simply customize the error output using nullMessage and emptyMessage, as described here: https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/13.2/Feature-102326-AllowCustomTranslationsForExtbaseValidators.html

However, this doesn’t seem to work.

How do you do this correctly?


If I understand correctly, it should be possible to customize error messages directly in the model. Right?

I have stripped down the model and controller to the bare minimum. Whenever my field to be validated is empty, the error from the errorAction is displayed instead of my custom messages from the model. I also checked the error output:

Array ( [0] => TYPO3\CMS\Extbase\Validation\Error Object ( 
    [message:protected] => Achtung Fehler 
    [code:protected] => 1221560718 
    [arguments:protected] => Array ( ) 
    [title:protected] => 
) ) 

This is exactly the expected error. And in 'message', my custom error message is present. However, it then goes into errorAction, where the FlashMessage is filled with: An error occurred while trying to call ' . static::class . '->' . $this->actionMethodName . '()'.

My model:

<?php
declare(strict_types=1);

namespace m3\Feuserfiles\Domain\Model;

use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
use TYPO3\CMS\Extbase\Annotation\Validate;

class Userfiles extends AbstractEntity
{

    #[Validate([
        'validator' => 'NotEmpty',
        'options' => [
            'nullMessage' => 'Achtung Fehler',
            'emptyMessage' => 'Achtung Fehler',
        ],
    ])]
    protected string $title = '';

    /**
     * @return string
     */
    public function getTitle(): string
    {
        return $this->title;
    }

    /**
     * @param string $title
     */
    public function setTitle(string $title): void
    {
        $this->title = $title;
    }

}

My Controller:

<?php

declare(strict_types=1);

namespace M3\Feuserfiles\Controller;

use M3\Feuserfiles\Domain\Model\Userfiles;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use M3\Feuserfiles\Domain\Repository\UserfilesRepository;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;

class UserfilesController extends ActionController
{
    /**
     * @var UserfilesRepository
     */
    protected UserfilesRepository $userfilesRepository;

    /**
     * Inject the files repository
     *
     * @param UserfilesRepository $userfilesRepository
     */
    public function injectFilesRepository(UserfilesRepository $userfilesRepository): void
    {
        $this->userfilesRepository = $userfilesRepository;
    }

    /**
     * @param Userfiles|null $userfiles
     * @return ResponseInterface
     */
    public function newAction(Userfiles $userfiles = null): ResponseInterface
    {
        $this->view->assign('userfile', $userfiles);
        return new HtmlResponse($this->view->render());
    }

    /**
     * @param Userfiles $userfiles
     * @return ResponseInterface
     * @throws IllegalObjectTypeException
     */
    public function createAction(Userfiles $userfiles): ResponseInterface
    {
        $this->userfilesRepository->add($userfiles);
        $this->addFlashMessage('Der Datensatz wurde erfolgreich angelegt.', '', ContextualFeedbackSeverity::OK);
        return $this->redirect('new');
    }

}

My Template:

<f:render partial="Misc/FlashMessages" arguments="{_all}" />
<f:form action="create" object="{userfile}" name="userfiles">
    <label for="title">Titel*</label>
    <f:form.textfield property="title" id="title" />
    <input type="submit" value="Datensatz speichern" />
</f:form>

Solution

  • So, your question has basically nothing to do with the referred TYPO3 core feature, but your problem is, that <f:flashMessages /> shows An error occurred while trying to call Vendor\Extension\Controller\MyController->createAction()

    This is the regular behavior of Extbase, when validation or mapping errors occured. In order to change or suppress the message, you must overwrite getErrorFlashMessage in your controller. If you want to suppress the message, add the following to your controller:

    /**
     * Suppress default validation messages
     */
    protected function getErrorFlashMessage(): bool
    {
        return false;
    }
    

    Also see the TYPO3 extbase documentation for details.

    Also note, that the f:flashMessages ViewHelper is not responsible for showing validation error messages. It only shows FlashMessages. If you want to output validation results, please use the f:form.validationResults ViewHelper as documented.