Search code examples
phpvalidationtwigformsslim-3

PHP - Displaying validation messages on a Twig view with a Slim 3 withRedirect() response


I’m trying to display validation error messages on a registration form. I’m using the Slim 3 framework for the routes and the Twig template system to display the html. Currently I'm trying to display error messages on the registration form if the user fails validation.

Here is the twig code for the registration form, note that {{email_error}}, {{username_error}} and {{password_error}} are Twig delimiters for printing out expressions which in my case is an error message for each input field.

register.html.twig:

{% extends 'header_footer.html.twig'%}
{% block content %}
    <h3>Register A New Account</h3>

    <form action = "{{ register_action }}" method = "post">
        <p>Email: <input type="text" name="email" value="{{ old.email }}" > {{ email_error }}<br></p>
        <p>Username: <input type="text" name="username" value="{{ old.username }}" > {{ username_error }}<br></p>
        <p>Password: <input type="text" name="password" > {{ password_error }}<br></p>
        <input type="submit" value="Create Account">
    </form>
{% endblock %}

I’ve managed to get this to work so far by rendering a new view and providing an array of options that has a string that represents the register Twig file delimiters and acts as the arrays index. The value of each index is then a call to a function of the ValidateSanitise class that simply returns an error message that is a String. When the user fails validation upon submitting the form, error messages are successfully displayed. Here is the code and the output:

return $this->container->view->render($response, 'register.html.twig',
    [
       'email_error' => $sanitizer_validator->get_validate_messages('email_error'),
       'username_error' => $sanitizer_validator->get_validate_messages('username_error'),
       'password_error' => $sanitizer_validator->get_validate_messages('password_error'),
    ]);

enter image description here

However I tried doing this with a Slim3 withRedirect() response rather than rendering out a new view and did the same thing where I provide an array of options, but for some reason no error messages appear if the user fails validation upon submitting the form, and the register page is redirected for the user to try again. Here is the code and the output:

return $response->withRedirect($this->container->router->pathFor('register',
    [    
        'email_error' => $sanitizer_validator->get_validate_messages('email_error'),
        'username_error' => $sanitizer_validator->get_validate_messages('username_error'),
        'password_error' => $sanitizer_validator->get_validate_messages('password_error'),
    ]));

enter image description here

My question is, how can I pass Strings (error messages) to a Slim 3 withRedirect() response to display on a Twig view? Is it possible to do so like I did with rendering out a new view in the first set of outputs?

Note I have already experimented with the Slim Respect Validation framework but I prefer my way of doing it.

Thanks, GR412


Solution

  • Before the redirect, you need to save messages to the session

    Before displaying the form, you need to take messages from the session.

    try using a package slim/flash

    require dirname(__FILE__).'/../vendor/autoload.php';
    
    session_start();
    
    $app = new \Slim\App();
    
    // Fetch DI Container
    $container = $app->getContainer();
    
    // Register provider
    $container['flash'] = function () {
        return new \Slim\Flash\Messages();
    };
    
    $container['view'] = function() {
        /*
         * init your render
         */
        $view = new Render();
        return $view;
    };
    
    
    $app->get('/form', function ($request, $response, $args = []) {
        return $this->view->render(
            $response,
            'register.html.twig',
            [
                'register_action' => $this->router->pathFor('post_form'),
                'email_error' => $this->flash->getFirstMessage('email_error'),
                'username_error' => $this->flash->getFirstMessage('username_error'),
                'password_error' => $this->flash->getFirstMessage('password_error'),
                'old' => [
                    'email' => $this->flash->getFirstMessage('old_email'),
                    'username' => $this->flash->getFirstMessage('old_username'),
                ],
            ]
        );
    })->setName('register');
    
    $app->post('/form', function ($request, $response, $args = []) {
        $post = $request->getParsedBody();
        $this->flash->addMessage('old_email', $post['email']);
        $this->flash->addMessage('old_username', $post['username']);
        $email_error = null;
        $username_error = null;
        $password_error = null;
        /*
         * Your handler
         */
        if ($email_error) {
            $this->flash->addMessage('email_error', $email_error);
        }
        if ($username_error) {
            $this->flash->addMessage('username_error', $username_error);
        }
        if ($password_error) {
            $this->flash->addMessage('password_error', $password_error);
        }
    
        return $response->withRedirect($this->router->pathFor('register'));
    })->setName('post_form');
    
    $app->run();