Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[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

Closed

Conversation

@javiereguiluz
Copy link
Member

@javiereguiluzjaviereguiluz commentedMar 1, 2017
edited
Loading

QA
Branch?master
Bug fix?no
New feature?yes
BC breaks?no
Deprecations?no
Tests pass?yes
Fixed tickets-
LicenseMIT
Doc PR-

Getting flash messages in templates is more complex than it could be. Main problems:

  1. It's too low level: you need to get the "flash bag" (and first, learn what a "flash bag" is) and then you need to call the internal method:all(),get(), etc.
  2. You need to be careful because the session will start automatically when you ask for flashes (even if there are no flashes). You can prevent this with the{% 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 newapp.flashes helper 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 typenotice

{%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 %}

theofidry, julienfalque, ro0NL, Hanmac, linaori, sstok, apfelbox, enleur, skigun, Pierstoval, and 2 more reacted with thumbs up emojirobfrawley, sstok, Pierstoval, devozanges, and apetitpa reacted with hooray emojiHeahDude, chalasr, yceruto, ogizanagi, robfrawley, hason, sstok, enleur, skigun, Pierstoval, and 2 more reacted with heart emoji
@javiereguiluzjaviereguiluz added DXDX = Developer eXperience (anything that improves the experience of using Symfony) Feature TwigBridge labelsMar 1, 2017
@stof
Copy link
Member

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.

Koc, apfelbox, and fmarcoux96 reacted with thumbs up emoji

* 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').
Copy link
Member

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.

javiereguiluz reacted with thumbs up emoji
@stof
Copy link
Member

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 acall_user_func_array equivalent to allow building arguments dynamically

ro0NL reacted with thumbs up emoji

@javiereguiluz
Copy link
MemberAuthor

I've replaced the variadic arguments by an array:

CodeResult
app.flashesnested array with all flashes
app.flashes('notice')simple array with flashes of that type
app.flashes(['notice'])nested array with type => messages
app.flashes(['notice', 'warning'])nested array with types => messages

@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.

robfrawley, yceruto, and sstok reacted with thumbs up emoji

if (null ===$types) {
return$session->getFlashBag()->all();
}

Copy link
Contributor

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;

javiereguiluz reacted with thumbs up emoji

if (1 ===count($types)) {
return$session->getFlashBag()->get($types[0]);
}
Copy link
Member

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

Copy link
Member

@chalasrchalasrMar 2, 2017
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

oops,@HeahDude commented meanwhile :)

Copy link
Contributor

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))?

Copy link
Contributor

@ro0NLro0NLMar 3, 2017
edited
Loading

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

Copy link
MemberAuthor

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
Copy link
Contributor

ro0NL commentedMar 3, 2017
edited
Loading

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

  • getFlashes($type = null) either all types nested, or a single type flat
  • getFlashes(array $types = null) for nested /getFlashesFor(array $types = null) for flat
  • {{ message.type ~ message.value }} flat with a nested message structure

if (null !==$session && !$session->isStarted()) {
returnarray();
}
}catch (\RuntimeException$e) {
Copy link
Contributor

@ro0NLro0NLMar 3, 2017
edited
Loading

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.

Copy link
MemberAuthor

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.

Copy link
Contributor

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.

@nicolas-grekasnicolas-grekas added this to the3.x milestoneMar 4, 2017
return$session->getFlashBag()->all();
}

$types = (array)$types;
Copy link
Contributor

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.

Copy link
Member

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
Copy link
MemberAuthor

Hopefully I have the code right this time. The idea is:

  • If you pass a string, you get a simple array with just those messages
  • If you pass an array, you get an array of messages
  • Otherwise, you get all messages ... except when the session hasn't started, where you get an empty array
yceruto reacted with thumbs up emoji

returnarray();
}

if (empty($types)) {
Copy link
Member

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
Copy link
Member

👍

@fabpot
Copy link
Member

Thank you@javiereguiluz.

@nicolas-grekasnicolas-grekas modified the milestones:3.x,3.3Mar 24, 2017
@ghostghost mentioned this pull requestMar 25, 2017
xabbuh added a commit to symfony/symfony-docs that referenced this pull requestApr 1, 2017
This PR was squashed before being merged into the master branch (closes#7684).Discussion----------#7676 - Flash messagesThis pull requestfixes#7676 that documents the flash messages that are been changed insymfony/symfony#21819.Commits-------467de14#7676 - Flash messages
@fabpotfabpot mentioned this pull requestMay 1, 2017
@Albert221
Copy link

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, flashmessage and redirect user; on 2nd request, I haveapp.flashes('message') in Twig, but it returns nothing, because I do not start session anywhere, I initially want it to exist, since I want to retrieve this flash, right?

@sroze
Copy link
Contributor

@Albert221 this has been fixed in this PR:https://github.com/symfony/symfony/pull/25077/files

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fabpotfabpotfabpot left review comments

@xabbuhxabbuhxabbuh left review comments

@ycerutoycerutoyceruto left review comments

@chalasrchalasrchalasr left review comments

+2 more reviewers

@ro0NLro0NLro0NL left review comments

@HeahDudeHeahDudeHeahDude left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

DXDX = Developer eXperience (anything that improves the experience of using Symfony)FeatureStatus: ReviewedTwigBridge

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

12 participants

@javiereguiluz@stof@ro0NL@fabpot@Albert221@sroze@xabbuh@yceruto@chalasr@HeahDude@nicolas-grekas@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp