Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[Twig Bridge] A simpler way to retrieve flash messages#21819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
stof commentedMar 1, 2017
Having a simpler API is a good idea. But I'm really not a fan of the magic API, which returns a nested array when you give 0 arguments or >2, but a flat array when you pass 1 argument. This is too magic. |
| * Returns some or all the existing flash messages. The method is variadic: | ||
| * if no arguments are passed, all flashes are returned; if one or more | ||
| * arguments are passed, only the flashes that belong to that category are | ||
| * returned; e.g. getFlashes('notice') or getFlashes('notice', 'error'). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Also we could support array of categories? i.e:getFlashes(['notice', 'error']), sometimes this information is configurable.
stof commentedMar 1, 2017
btw, to get some types only, an array would be better than a variadic function IMO. Twig does not have the spread operator, and does not have a |
javiereguiluz commentedMar 2, 2017
I've replaced the variadic arguments by an array:
@stof I take your comment into consideration, but in this case, instead of "magic API" I think it's "smart/flexible API". It's similar to when Symfony lets you pass a string to a config option that needs an array and does the string -> array conversion automatically. I think that returning a nested array when you ask for the flash messages of a single type is cumbersome: {# you would need to use this...#}{%formessagein app.flashes('notice')['notice'] %} <divclass="alert alert-notice"> {{message }} </div>{%endfor %}{# ... or this ...#}{%fortype,messagesin app.flashes('notice') %} {%formessageinmessages %} <divclass="alert alert-notice"> {{message }} </div> {%endfor %}{%endfor %}{# ... instead of this:#}{%formessagein app.flashes('notice') %} <divclass="alert alert-notice"> {{message }} </div>{%endfor %} But I'm open to other comments and opinions about this. Let's work together to make a great API that doesn't feel magic! Thanks. |
| if (null ===$types) { | ||
| return$session->getFlashBag()->all(); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
You should cast $types to an array first:
$type = (array)$type;
| if (1 ===count($types)) { | ||
| return$session->getFlashBag()->get($types[0]); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Calling this method with a string like"notice" as argument would make this check pass andget('n') to be called
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
oops,@HeahDude commented meanwhile :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Either way.. offset 0 may not exist :) What about->get(reset($types))?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Oh and it violates the api (more or less) withgetFlashes(['notice']) (i'd expect a nested array... but you get a flat one).
edit: yeah.. already pointed out by@stof , but it's now advertised with
app.flashes(['notice'])nested array with type => messages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@ro0NL good catch about the potential non-existent 0 offset. I've added... || empty($types) condition to return all the flashes in that case.
ro0NL commentedMar 3, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Not sure about the mixed api.. i could live with it i guess. In twig context it's probably less an issue, and once you know it you're good to go :) Some other thoughts
|
| if (null !==$session && !$session->isStarted()) { | ||
| returnarray(); | ||
| } | ||
| }catch (\RuntimeException$e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This may be too broad, only to bypassThe "app.session" variable is not available.. I guess it's an edge case :) but maybe do a quick return array() as well if there's no request stack and drop the try/catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Yes ... it's tricky. But avoiding the try...catch would require to duplicate some of the code of this very same class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would checkrequestStack here, and rely ongetSession to be available otherwise.
| return$session->getFlashBag()->all(); | ||
| } | ||
| $types = (array)$types; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Again.. offset 0 may not exist ;-) also the API is still inconsistent withflashes(['single']) vs.flashes('single'). Both return flat, not just the latter. Like@stof mentioned.. this is too magic.
What about
if (null ===$types ||array() ===$types) {return$session->getFlashBag()->all();}if (!is_array($types)) {return$session->getFlashBag()->get($types);}// intersect
Theempty check is too magic (for me) as well; passing"0", "", etc. should be passed toget() IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I agree that's not very intuitive. Imagine the case where the exact parameter passed to the Twig function is dynamic. You then don't know beforehand whether or not you will get a flat or a nested array. What we could however is to always return the nested array if you pass an array as the argument (no matter the number of arguments) and get the flat result when a string is given.
javiereguiluz commentedMar 4, 2017
Hopefully I have the code right this time. The idea is:
|
| returnarray(); | ||
| } | ||
| if (empty($types)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
null !== $type || array() === $types to allow0 as a type.
fabpot commentedMar 23, 2017
👍 |
fabpot commentedMar 23, 2017
Thank you@javiereguiluz. |
Albert221 commentedNov 26, 2017
Hey@javiereguiluz, can you explain to me, why starting session once getting flash messages is not an intended behaviour, please? I had given scenario: on 1st request, flash |
sroze commentedNov 26, 2017
@Albert221 this has been fixed in this PR:https://github.com/symfony/symfony/pull/25077/files |
Uh oh!
There was an error while loading.Please reload this page.
Getting flash messages in templates is more complex than it could be. Main problems:
all(),get(), etc.{% if app.session is not null and app.session.started %}code, but it's boring to always use that.So, I propose to add a new
app.flasheshelper that works as follows.Get all the flash messages
Before
{%ifapp.sessionis notnullandapp.session.started %} {%forlabel,messagesinapp.session.flashbag.all %} {%formessageinmessages %} <divclass="alert alert-{{label }}"> {{message }} </div> {%endfor %} {%endfor %}{%endif %}After
{%forlabel,messagesinapp.flashes %} {%formessageinmessages %} <divclass="alert alert-{{label }}"> {{message }} </div> {%endfor %}{%endfor %}Get only the flashes of type
notice{%ifapp.sessionis notnullandapp.session.started %} {%formessageinapp.session.flashbag.get('notice') %} <divclass="alert alert-notice"> {{message }} </div> {%endfor %}{%endif %}After
{%formessagein app.flashes('notice') %} <divclass="alert alert-notice"> {{message }} </div>{%endfor %}As an added bonus, you can get any number of flash messages because the method allows to pass an array of flash types:
{%forlabel,messagesin app.flashes(['warning','error']) %} {%formessageinmessages %} <divclass="alert alert-{{label }}"> {{message }} </div> {%endfor %}{%endfor %}