11

Flash messages seems to be broken in case of redirecting. I made simple test code:

public function actionTest($test = 0) {
    if($test == 0) {
        Yii::$app->getSession()->addFlash('success', 'Follow the white rabbit');
        return Yii::$app->getResponse()->redirect(array('test', 'test' => 1));
    }
    return $this->render('test', []);
}

I call the action without parameter, it adds a flash and redirects. When it renders the page - flash is not present.

The view part is fine, because if I set flash and make a render without redirect it is rendered properly.

Why?

EDIT: Layout view code:

<?php

use frontend\widgets\Alert;

$this->beginPage();
echo $this->render('partials/head');
?>

<body class="no-sidebar">
    <?= $this->beginBody() ?>
    <div id="header">
        <?= $this->render('partials/top') ?>
        <?= $this->render(Yii::$app->user->isGuest ? 'menus/guest' : 'menus/registered') ?>
    </div>
    <!-- Main -->
    <div id="main">
        <?= Alert::widget() ?>
        <?= $content ?>

    </div>

    <?= $this->render('partials/footer') ?>
    <?= $this->endBody() ?>
</body>
</html>

<?php $this->endPage() ?>
Joe
  • 2,551
  • 6
  • 38
  • 60

7 Answers7

29

I've gotten the same error until I found out that the return is missing in my code. So, with return $this->redirect() it works just fine and with $this->redirect it does not work well.

user5653303
  • 306
  • 3
  • 2
  • 1
    It makes sense. If you use redirect without return the script goes on, it renders the page, it uses up the flashes then it redirects. The result is a missing flash on the next page. So it is normal and expected behavior. – Mihai P. Apr 20 '16 at 04:39
  • 1
    Man you saved my bacon. I spent hours screwing around with this problem until I read your comment. Fixed it immediately. Thank you! – Alec Smythe Feb 09 '17 at 20:47
5

Your code looks ok, I am not sure what the problem is. You can try using

return $this->redirect(['test', 'test' => 1]);

Instead of

return Yii::$app->getResponse()->redirect(array('test', 'test' => 1));

This is how most Yii examples are. But your code looks ok after looking at http://www.yiiframework.com/doc-2.0/yii-web-response.html#redirect()-detail

Are you sure your session is working properly and you are not destroying it at any point?

This works for me:

public function actionChangeDetails()
    {
        $model = Contact::findOne(Yii::$app->user->identity->id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            Yii::$app->session->setFlash('success', 'Form Saved');
            return Yii::$app->getResponse()->redirect(['my-account/change-details']);
        }

        return $this->render('changeDetails', [
            'model' => $model,
        ]);
    }
Mihai P.
  • 9,307
  • 3
  • 38
  • 49
  • Simple `$this->redirect` would work (I tested it in new Yii2 project), but I can't do that in my case because I have to return Response object. I asked at yii2 github and they couldn't reproduce. Maybe it is some kind of session problem but for now it's hard to find. I am not destroying session anywhere for sure. – Joe Oct 07 '14 at 06:24
  • Try it with the latest Yii, maybe you do not have an updated one. – Mihai P. Oct 07 '14 at 07:19
  • Nope, I created new app using composer. – Joe Oct 07 '14 at 08:36
  • `$this->redirect` actually calls `Yii::$app->getResponse()->redirect(Url::to($url), $statusCode);` so there is no difference between the 2 functions. But I can confirm the issue, I tested it myself on my app and it does exactly how you describe it. Can you give me the bug report that you have done so I may raise the problem again? – Mihai P. Oct 08 '14 at 04:06
  • I added the code like it works for me in the main answer. I tested it on my app and it works just fine. I personally do not usually use `return Yii::$app->getResponse()->redirect(['my-account/change-details']);` as there is no point to it. – Mihai P. Oct 08 '14 at 04:20
  • I cannot replicate it anymore :( I tried and right now it all works. 5 minutes after I wrote that it all worked ok, no idea what changed. Can you try using setFlash instead of addFlash see if that makes a difference? – Mihai P. Oct 09 '14 at 04:02
  • Actually I made new test app and it worked. What was the mistake? I have no idea. Thanks for help anyway. – Joe Oct 22 '14 at 11:37
2

I have a solution: You can add the line below in the view file where the message is to appear:

Then you can add the line below in the view file, where the message is supposed to appear.

if(Yii::$app->getResponse()->getStatusCode() != 302) {
   Yii::$app->session->getFlash('error');
}

Or alternatively, you can add the line below in the content layout

<?= Alert::widget() ?>
// Before the line
<?= $content ?>
// in app/views/layouts/_content.php 
// Depending on how you arranged your files.
Paul Wakhungu
  • 322
  • 2
  • 18
HeadHunter
  • 21
  • 2
  • 1
    Welcome to Stack Overflow! Could you explain how your answer addresses the problem(s) from the question? Code-only answers are not very useful, especially for further readers that stumble upon this post. Thanks! – Cristik Jun 14 '16 at 04:13
2

Add return in your redirect

Yii::$app->session->getFlash('key', 'message');

return $this->redirect(['yourAction']);
Neels
  • 2,547
  • 6
  • 33
  • 40
1

On the view page you should add: 'session->getFlash('success'); ?>' like it is described here: Yii2 Session, Flash messages, then you will see your flash message

Community
  • 1
  • 1
Anaxarchos
  • 11
  • 3
1

In my case flash messages weren't available when I was redirecting from beforeAction method. And using Yii::$app->end() really helped me. Here is my code:

public function beforeAction($action) {
    if ($someVariableIs === false) {
        Yii::$app->session->addFlash("negative", "My flash message");
        Yii::$app->getResponse()->redirect(["/path/to/redirect"]);
        Yii::$app->end();
    }

    // some of your code...

    return true;
}

Hope it'll help someone.

Akmal
  • 543
  • 7
  • 13
0

This worked for me

since I noticed flashes works when view is rendered, i pass the flash message on redirect url

      public function someFunction(){
        $flash_msg = "Warning! You cannot create an assessment that is not linked to participant."; 
        return $this->redirect(['controllerID/index', 'msg' => $flash_msg]);
      }

in my index function check if the message is set, then flash it;

public function actionCreate()
{
    $model = new Model();

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    } else {
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}
Wainaina Nik
  • 163
  • 1
  • 8