odan / slim4-skeleton

A Slim 4 Skeleton
https://odan.github.io/slim4-skeleton/
MIT License
439 stars 80 forks source link

Flash Messages #45

Closed nmatias closed 3 years ago

nmatias commented 3 years ago

I update my code with the changes done in the container (Reverted session handler. Fixed session starts by lazy loading the fl 8 August), but now, this code doesn't work anymore:

{% for label, messages in flashbag.all %} {% for message in messages %} .... {% endfor %} {% endfor %}

but

{% for message in flashes('success') %}

{% endfor %}

work.

My question id with the first version, i can reduce the code to use with BootstrapNotify. I always spend some hours to resolve this issue but i don't find the solution yet.

Thanks.

odan commented 3 years ago

I guess you mean this changes: 1, 2 where the global Twig variable flash was replaced with the flashes TwigFunction to fix the session start time when the getFlashBag method is getting called.

If I understand you correctly, you are trying to get access to the FlashBag instance directly.

I have not tested it, but you could try this workaround.

Add this container entry for the FlashBagInterface:

use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;

// ...
FlashBagInterface::class => function (ContainerInterface $container) {
    return $container->get(Session::class)->getFlashBag();
},

Then change the flashes Twig function as follows:

$environment->addFunction(
    new TwigFunction(
        'flashes',
        function (string $key, $default = null) use ($container) {
            // Lazy loading the flashbag to prevent session from starting
            return $container->get(FlashBagInterface::class)->get($key, $default ?? []);
        }
    )
);

Add the new flashbag global Twig variable as follows:

$twig->getEnvironment()->addGlobal(
    'flashbag',
    new class($container) {
        private $container;

        public function __construct($container)
        {
            $this->container = $container;
        }

        public function __call($name, $arguments)
        {
            return call_user_func_array([$this->container->get(FlashBagInterface::class), $name], $arguments);
        }
    }
);

Twig usage example:

{% for label, messages in flashbag.all %}
    {% for message in messages %}
        {{ message|trans }}
    {% endfor %}
{% endfor %}
nmatias commented 3 years ago

Thanks Daniel,

The solution work well. I think I understand the workaround. I thinked that the data obtain from the flashes was the same like I try directly in the flashbag var in PHP but it's only possible if the flashbag var are turn global on twig. Tricky 👍 .

Thank again!