9

I set a flash message in a controller with the following code:

$this->get('session')->getFlashBag()->add('success', 'Message sent successfully');

And in my template, I use the following to (attempt to) display it:

{% if app.session.flashbag.has('success') %}
    <div id="flash">
        {{ app.session.flashbag.get('success') }}
    </div>
{% endif %}

The problem is that, despite the API documentation stating that get returns a string, I'm getting an array to string conversion exception. If I change the code in the template to:

{% for flashMessage in app.session.flashbag.get('success') %}
    <div id="flash">
        {{ flashMessage }}
    </div>
{% endfor %}

It works perfectly. I'd rather not use a loop here since I'm only ever either going to have the single message or not.

Is there a solution where I can just check for the existence of a single flash message and display it if it's there? Or am I stuck with a useless loop?

4 Answers 4

11

Solved it by indexing at 0:

{{ app.session.flashbag.get('success')[0] }}

My suspicions were correct - get returns an array rather than a string. Here's the flashbag's add method:

public function add($type, $message)
{
    $this->flashes[$type][] = $message;
}

And get:

public function get($type, array $default = array())
{
    if (!$this->has($type)) {
        return $default;
    }

    $return = $this->flashes[$type];

    unset($this->flashes[$type]);

    return $return;
}

They need to fix the API documentation so it reflects reality. They should also provide an elegant way to handle a single flash message.

EDIT: A backwards compatible (PHP 5.3 and below) version -

{% if app.session.flashbag.has('success') %}
    {% set flashbag = app.session.flashbag.get('success') %}
    {% set message = flashbag[0] %}
    <div id="flash">
        {{ message }}
    </div>
{% endif %}
Sign up to request clarification or add additional context in comments.

1 Comment

9 months and still the doc is lagging
4

For one flash message:

{{ app.session.flashbag.get('success')[0] }}

For all:

{% for type, messages in app.session.flashbag.all() %}
    {% for message in messages %}
        <div class="alert alert-{{ type }}">
            {{ message }}
        </div>
    {% endfor %}
{% endfor %}

Comments

1

I've just hit this myself. It was because I was using the add() method instead of set().

The differences between Add and Set:

public function add($type, $message)
{
    $this->flashes[$type][] = $message;
}

The above would add an extra array which isn't required in this case.

Whereas:

public function set($type, $messages)
{
    $this->flashes[$type] = (array) $messages;
}

So set() results in $array[$key] = $value, rather than what add does, which is $array[$key][] = $value which is what is causing your Array to string conversion because you're passing an array, not a string.

Comments

0

OK, I see that you have resolved this issue by yourself but this might be an easier way:

{% if app.session.hasFlash('success') %}
    {{ app.session.flash('success') }}
{% endif %}

... since you can't guarantee that there will always be at least flash message ;)

2 Comments

That is easier, and is what I originally had. The problem is that way of doing it will be deprecated by 2.3, so in order to futureproof I decided to use the flashbag.
Ah, I haven't got time yet to read 2.3 changelog. Thanks for the info :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.