We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Acl Redirect instead of Dispatch

Hello!

I'm working on some project where I need access list for selected actions. I've taken some code from INVO and it work as expected. The problem is that dispatcher only gets view and things from selected action, but doesn't change URL. I could do that easily with Http library and response/redirect, but than I get two flashSession messages instead of just one. What can I do to solve that problem?

Thank you in advance! :)

edited Aug '14

Do something like this:

<?php
namespace Helper;
/**
 * Description of Flash
 *
 * @author Webvizitky, Softdream <[email protected]>,<[email protected]>
 * @copyright (c) 2013, Softdream, Webvizitky
 * @package name
 * @category name
 * 
 */
class Flash {
    protected static $instance;

    /**
     * @var \Phalcon\Flash flash adapter
     */
    protected $adapter;

    private function __construct() {

    }

    /**
     * Get created instance of object
     * @return \Helper\Flash Description
     */
    protected static function getInstance(){
    if(!self::$instance){
        self::$instance = new self();
    }

    return self::$instance;
    }

    public function setAdapter($adapter){
    $this->adapter = $adapter;
    }

    /**
     * @return \Phalcon\Flash Description
     */
    public function getAdapter(){
    return $this->adapter;
    }

    public function init(){
    if(!$this->adapter){
        throw new \Exception('Adapter is not set.');
    }
    }

    public static function registerAdapter(\Phalcon\Flash $adapter){
    $instance = self::getInstance();
    if(!$instance->getAdapter()){
        $instance->setAdapter($adapter);
    }
    }

    public static function warning($message, \Phalcon\Flash $adapter = null){

    $instance = self::getInstance();
    if($adapter && !$instance->getAdapter()){
        $instance->registerAdapter($adapter);
    }
    $instance->init();

    $adapter = $instance->getAdapter();
    foreach($message as $msg){
        $adapter->warning($msg);
    }

    }

    public static function notice($message, \Phalcon\Flash $adapter = null){
    $instance = self::getInstance();
    if($adapter && !$instance->getAdapter()){
        $instance->registerAdapter($adapter);
    }

    $instance->init();

    $adapter = $instance->getAdapter();
    foreach($message as $msg){
        $adapter->notice($msg);
    }
    }
    public static function success($message, \Phalcon\Adapter $adapter = null){
    $instance = self::getInstance();
    if($adapter && !$instance->getAdapter()){
        $instance->registerAdapter($adapter);
    }
    $instance->init();

    $adapter = $instance->getAdapter();
    foreach($message as $msg){
        $adapter->success($msg);
    }
    }
    public static function error($message, \Phalcon\Flash $adapter = null){
    $instance = self::getInstance();
    if($adapter && !$instance->getAdapter()){
        $instance->registerAdapter($adapter);
    }
    $instance->init();

    $adapter = $instance->getAdapter();
    foreach($message as $msg){
        $adapter->error($msg);
    }
    }
}

And just move $adapter->error(), success(), waring(), notice() below to the loop and in the loop set join string like this:

foreach($message as $msg){
        $msgs .= $msg.'<br />';
}

$adapter->notice($msg);

So with this solution you can throw more then one errors in one flash messages. And how to use it:

if(!$validEmail){
   $err[] = 'My first error';
}

$err[] = 'My second error';

\Helper\Flash::notice($err,$this->flash);

I hope this help. You can do it with singlenton too, and appending errors into singlenton object, then throw it. With this solution you can check, if the error message has been set before or not, with just create a help variable to store hash of messages.

I don't see what's the difference between custom Flash helper and included one in Phalcon in my case except checking for exsistence of message. The problem is that I need to get flashSession messages somehow through redirect without duplicating or to change URL with dispatcher somehow (I don't believe this is possible). It must be easier solution since I'm not the only one who needs something like that.

I hope anyone can provide easier solution. Thank you!

Sure it is, i think that you have problem with implementation of flashSession, maybe dual call {{ flash.output() }} at the template. Because i doesn't have problems with flash messages after redirect. Just one, sometimes the message doesn't show, but it can be resolved in replacing response redirect method.

Try this out: https://pastebin.com/ABLMjgnm And replace in bootstrap default response to this one, it will help with stop script at the redirect and doesn't continue the request. And check in your templates if you don't have two calling flash.outpu();

But i think that could be helpful in resolving your problem to show part of code where it happen.

I found out where's the problem, but currently I don't know how to solve it. If I open URL pointed as route I got two same messages from flashSession->error('some message');. Opposite thing is if I open direct URL by controller name... than there is no any problem and I got only one message from flashSession as expected.

Hmmm... I will look at my config of routes and in documentation. Interesting :)

When you do your forward or redirect are you using it with a return?

return $this->response->redirect();

I'm using it that way:

$this->flashSession->error('some message');

return $this->response->redirect('route');

It seems that problem is only when I redirect request to route with action in different controller. If I redirect request inside the same controller or directly without route it's working good.

Somewhere in your code must be matching the route twice hence 2 flash messages are shown. What does your routes file look like?

edited Aug '14

Routes file is also the same as Vokuro's. I found out that sometimes duplicated message is also present when I open full URL -> controller/action.

I really don't know what could be wrong and what to look for...

EDIT: It seems that something is wrong with Chromium, because I can't reproduce this error in Firefox. In Firefox is everything as expected... weird.