Pathros
Pathros

Reputation: 10730

Slim framework 3: how to get parameters from a redirect from a post route inside a get route

This may seem a simple example but I am stuck. I am watching a tutorial where we see a contact form that has its own get route to render a view that contains the already said contact form.

$app->get('/contact',function (Request $request, Response $response){
    return $this->view->render($response,'contact.twig');
})->setName('contact');

Then we have a post that gets the posted data through that form (notice I am passing the data that has been collected from the form).

$app->post('/contact',function ($request,$response){
    $data = $request->getParams();
    //var_dump($data);

    return $response->withRedirect($this->router->pathFor('contact.confirmed', ['data' => $data]));//https://github.com/slimphp/Slim/issues/1933

})->setName('contact');

Finally we have another get route to render a confirmation view that lets the user know that the information has been submitted successfully.

$app->get('/contact/confirmed',function(Request $request, Response $response, $data){

    echo 'params are';
    var_dump($data);//They never show! :(

    return $this->view->render($response,'contact_confirm.twig',[
        'data'  =>  $request->getParams(),
    ]);//https://github.com/slimphp/Slim/issues/1579
})->setName('contact.confirmed');

In that confirmation view, I want to retrieve the data submitted in the post route just to call the user by their name but I get an error saying that $data is empty.

I have been struggling on how to retrieve the user's name.

As a workaround, I have solved it by rendering the view right from the post route ...

$app->post('/contact',function ($request,$response){
    $data = $request->getParams();
    //var_dump($data);

    return $response->withRedirect($this->router->pathFor('contact.confirmed', ['data' => $data]));//https://github.com/slimphp/Slim/issues/1933

})->setName('contact');

but then I wonder why bothering to use withRedirect() function?

My question is, how do I pass data or parameters from a post route to a get route wher you use a withRedirect() function? And in the get route, how do you retrieve those parameters? So I can pass them to its corresponding view.

Solved

Thanks to jmattheis this is how I solved it:

I just happened to learn how to use controllers in slim framework 3, so the ContactController.php looks like:

<?php

namespace App\Controllers\contact;

use App\Controllers\Controller;

class ContactController extends Controller
{
    public function show($request,$response)
    {
        return $this->c->view->render($response,'contact.twig');
    }

    public function store($request,$response)
    {
        echo 'storing comments in db ...';
        $data = $request->getParams();
        //var_dump($data);
        //echo 'Name is: '.$data['name'];
        $this->c->flash->addMessage('data', $data);
        return $response->withRedirect($this->c->router->pathFor('contact.success'));
    }

    public function success($request,$response,$data)
    {
        //echo 'Data to be sent in the redirect: ';
        $data = $this->c->flash->getFirstMessage('data');
        //var_dump($data);
        //die();
        return $this->c->view->render($response,'contact_success.twig',compact('data'));
    }
}

And I added the following code

session_start();
ini_set('date.timezone', 'America/Mexico_City');

right before

$app = new App([
    'settings'  =>  [
        'displayErrorDetails'   =>  true
    ]
]);

And that did the trick.

Upvotes: 0

Views: 3531

Answers (2)

Georgy Ivanov
Georgy Ivanov

Reputation: 1579

Assuming that confirmation template is rendered only after form is being processed, there is no need to declare a separate GET route for such view.

So, keep the route that renders the form:

// This route renders the contact form.
$app->get('/contact', function ($request, $response) {

    return $this->view->render($response, 'contact.twig');

})->setName('contact');

And render contact_confirm.twig only as result of form being posted:

// This route is contact form processor.
$app->post('/contact', function ($request, $response) {

    // Get submitted data.
    $formData = $request->getParams();

    // Process form data, e.g. store it, sending it somewhere...

    // Render confirmation template, passing user name as template parameter.
    $templateParams = [
        'userName' => $formData['userName'] ?? 'Name unknown';
    ];

    return $this->view->render($response, 'contact_confirmed.twig', $templateParams);

});

Upvotes: 0

jmattheis
jmattheis

Reputation: 11125

You can't transfer data over a redirect. The second parameter from the pathFor method on the router is the array for the named paramters. That would be f.ex. id in the route /user/{id} then you'd had to put ['id' => 1] in it.

If you $data has a simple structur, then you could put them in the 3rd parameter which are the query params and later read them out with $request->getQueryParams()

$this->router->pathFor('contact.confirmed', [], $data);

Alternative, you could put the data in a session variable, slimphp/Slim-Flash is a library who that.

Example:

$app->post('/contact',function ($request,$response){
    $data = $request->getParams();
    $this->flash->addMessage('data', $data);
    return $response->withRedirect($this->router->pathFor('contact.confirmed'));
})->setName('contact');

$app->get('/contact/confirmed',function(Request $request, Response $response, $data){
    $data = $this->flash->getFirstMessage('data');
    // ...
});

Upvotes: 3

Related Questions