Symfony2 - Array to string conversion exception with a flash message
Asked Answered
S

4

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?

Sundowner answered 23/3, 2013 at 1:17 Comment(0)
S
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 %}
Sundowner answered 23/3, 2013 at 1:43 Comment(1)
9 months and still the doc is laggingRover
I
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 %}
Inclinometer answered 23/3, 2013 at 12:59 Comment(0)
E
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.

Edgebone answered 8/10, 2015 at 11:35 Comment(0)
S
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 ;)

Susurration answered 23/3, 2013 at 7:35 Comment(2)
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.Sundowner
Ah, I haven't got time yet to read 2.3 changelog. Thanks for the info :)Susurration

© 2022 - 2024 — McMap. All rights reserved.