BenSmith's avatar

New blade tag for unescaped data. Thoughts?

I've been messing around with 4.3 for the past couple of days and today I did a composer update right in the middle of Taylor fixing/changing a load of stuff. Was causing me some errors so I decided to look at the recent changes and noticed this Tweak how Blade echo escaping works for more safety.

This change is in conjunction with making both {{ }} and {{{ }}} escape values by default. This means that {{ link_to_route('login_path') }} will no longer output the html to the page and you will instead have to use {!! link_to_route('login_path') !!} .

I'm for the change as it reduces the risk of code injection but I do think it will break a lot of existing code. Will this make the next version more likely to be 5.0 than 4.3?. I'm also worried that it will mean yet more delays to get full blade support for PHPStorm :)

What are your thoughts?

0 likes
34 replies
abbyjanke's avatar

Ahaha! Thank you for this post. I was just about to start digging into the commits to see what changed because I noticed my forms were no longer working.

Honestly, the change will be nice in the long run. I don't like the {!! !!} as it is completely new concept and will likely cause some confusion especially for me in the short term, but I do think it will be a nice change.

Again, thanks for the post before I spent abit digging around :)

danharper's avatar

Have no idea if it's planned, but I like what Handlebar.js allows you to do: your helpers (think link_to_route) can return either a string, which will be treated as anything else, or an instead of Handlebars.SafeString which is considered already safe and is output unescaped.

Guess Laravel could do something similar for these helpers..

akael's avatar

@BenSmith I don't think it will have much effect on PHPStorm since they pretty much have the blade system working in the EAP, and are still actively developing it.

I think if this change sticks (I expect it to) the PHPStorm guys will add in the feature pretty darn quickly since Laravel is so popular right now.

Valorin's avatar

I'm not a fan of the change. Using {{ }} for normal variables and {{{ }}} for escaped variables made sense to me and just worked. But now having to remember a completely different option {!! !!} just seems counter-intuitive. Given it will break all existing useage of the HTML:: and Form:: facades, it's going to be painful.

That said, if he's bumping to v5.0 instead of v4.3, it'll be less annoying, and @danharper's suggestion of the magic to make {{ HTML::blah() }} work would be fantastic.

A few months until release... we shall see what happens.

rspahni's avatar

In my mind there's no doubt anymore that we're seeing 5.0 arise not 4.3; this is now going way beyond the original "one hour or so to migrate" scope. I have been brave (stupid?) enough to migrate my ongoing project already [the effort to keep up with Taylor has been adding up quite a bit lately, so can't really recommend anyone to follow my example] and looking over my updated blades I'll admit that the {!! !!} tag is really expressive in terms of visualizing the risk implied in these spots. Whether or not this warrants the effort of updating and re-testing 100+ tags in my case, I'm not sure either but it's survivable for sure. In any case we should not forget that Form and Html have been removed from the Laravel core, so Taylor may not feel too empathetic with those who will continue to use these facades.

1 like
BenSmith's avatar

100% agree with you, we're now seeing 5.0, the changes are too comprehensive for anything else. I think it would be wise for Taylor to confirm that this is the case so that people know what they're getting themselves into if they decide to make the jump early.

I'm still somewhat surprised about the form class being dropped. I can see the reasoning but to me forms are such a fundamental part of web development that having no built in way of making it as easy as possible to create them is a bit strange.

I've spent a bit of time recently trying out Ruby on Rails to see how Laravel compares and I was really impressed with how easy it was to make forms and populate them with the necessary information.

rspahni's avatar

Likewise, 100% agree with you re forms. While I can see that this may not be the conceptually most sophisticated thing, may be error/PR prone, etc., I believe it added/adds tremendous value in the non-sophisticated everyday groundwork and as that, has its value in marketing Laravel to regular people looking around for a tool that helps them to get stuff done. Like me who is easier to impress with Forms than with method injection (that's how simple I am). Or anecdotally, it would be interesting to count how many times @jeff_way has referred to the Form facade since Laracasts was launched... I hear/understand that Form is supposed to be further maintained by whomever but would feel much more confident if that happened as part of the core. Surely, can be swapped out / substituted like anything else but not something I'm craving to do. I'd rather feel tempted, too, to see whether Ruby, Fuel or any alternative might stick with the all-round approach incl. front-end.

Valorin's avatar

I can understand the Form class being extracted - since a lot of developers are moving towards Javascript-heavy applications, where the forms are generated in the browser and Ajax requests do all of the heavy lifting. Also with UI frameworks which have specific form formatting rules, you're either left with horribly complicated wrapper around Form calls, or you just extend it anyway.

HTML however is harder to understand, since it provides helper functions to generate URLs based on routes, controller actions, etc. I guess the URL Facade will still exist, so we'll just have to render our own HTML around the URL... in hindsight, this also fits with the increase in JS apps and UI frameworks - both of which would do their own link generation.

As a side note, the new escaped {{ }} would probably work fine with the URL Facade, since it doesn't generate HTML - just the raw URL to go inside it.

So... all this in mind, maybe {!! !!} makes sense - it seems to be something we'll be doing less often without custom helpers.

rspahni's avatar

For the record, generic URL helpers like link_to_route are a thing of the past as of yesterday: https://github.com/laravel/framework/commit/20080563a02f7e6a9932a8f974d237baf737b45d. The URL facade is still there. My current app is pretty JS heavy but personally I often don't see the point of generating 80:20 static forms with JS & Ajax so the Form facade has been remained useful. But of course, if all goes wrong we can simply go back to echoing plain old html.

rspahni's avatar

Ah great observation, thx. Have never used them anyway but good to know.

TaylorOtwell's avatar
Level 5

Thanks for the thoughts everyone. Should point out that that you will be able to do Blade::setRawTags($openTag, $closeTag) to set the raw tags back to {{ }} if you wish.

As another poster mentioned, the HTML and Form components are not "deleted", but merely dropped from the core. There are a few reasons for this, but the primary one is to turn Form and HTML helpers over the innovation of the community at large. There are several different approaches to writing forms and it's actually a pretty complicated topic. I would rather let the community hack on that and release several cool packages that can occupy that space.

Regarding Laravel 4.3 vs. Laravel 5.0 - I am leaning with 5.0 at this point, even though I still feel the upgrade isn't that large, especially if you use providers for running the legacy folder structure and use the Blade::setRawTags method to keep the current Blade escaping logic.

13 likes
alfrednutile's avatar

I know the typical answer is "any where you want" :) but where is the best place to centralize settings like this

Blade::setRawTags('{{', '}}');
JeffreyWay's avatar

Thanks for chiming in @TaylorOtwell!

@alfrednutile Again, really anywhere you want. :) But you could put it in a service provider. You might start with the AppServiceProvider that is included, by default.

rspahni's avatar

Just be aware that AppServiceProvider by [current] default is called first in the "providers" section in config.app.php i.e. some stuff will be bootstrapped only later in the request cycle and therefore cannot be easily referenced in AppServiceProvider. Unless you move it down the list of providers, or create your own and call it toward the end of the providers list (my approach).

Rtransat's avatar

I really don't understand why the raw tags are changed. I would like to know why "{!!" it's better than "{{" ?

But if we still can change the raw tags with a method it's good to me :).

BenSmith's avatar

Thanks for the reply Taylor. Whilst changing the structure may not be a big update to the way the framework works internally, for us mere mortals it's a huge departure from what we've been used to, both in terms of file placement but also the bringing of service providers to prominence.

The providers for the legacy application and the setRawTags helper method will shorten the upgrade process, however when I am updating (and I may well be a small minority here), I want my code to be as idiomatic to the framework as possible. With all the changes this could easily take a few hours, moving files into their correct places, adding requests, updating blade tags etc.

The more I have thought about it, the more I agree with the removal of form and html from the core, my only worry is that new members of the community may completely miss out on what can be a huge timesaver. If Laracasts were to release a (free?) video about the form and html packages it would give us a place to point new users if they were writing out forms manually. All in all though, the new additions are incredible, thanks Taylor.

@rspahni - The service provider ordering bit me yesterday when I was trying to set up a provider for adding view composers. In the end I just created a base controller and stuck it in there like I used to.

1 like
rspahni's avatar

@BenSmith totally share your sentiment re adhering to the framework, thus have bravely gone through the pain of updating my tags and, honestly, found many places where I used to use the raw tag for no reason and could leave the {{ }} untouched... :) Re service providers, I am slowly becoming an aficionado, however, especially when not being mindful enough of what is called when or - even worse - confusing boot and register methods, I find the error messages coming from them very hard to decipher. Hello Xdebug and learning curve.

Flatline's avatar

I really like the new direction, and I don't really mind the blade changes. That being said, I do think this looks a lot more like a 5.0 version, not that there's anything wrong with that.

@BenSmith you're not alone :P I also like to do that, so I'll most likely ignore the legacy providers, that means more work when updating, but the truth is that the changes are good enough to make me want to switch without worrying about the migration work. In fact, I'm tempted to migrate now, unstable and all.

JordanDalton's avatar

I'm not a fan of this change. I think the way it was originally was very simple. It seems to me that this could/should be set in a blade config file instead of a service provider.

thepsion5's avatar

Personally, I'd prefer {{! foo() !}} vs {!! foo() !!}, just because it's more consistent with blade's syntax. But it won't be a big deal either way.

It helps that my current big project at work is an API and I haven't had to care about blade in about 3 months. ;)

1 like
joselara's avatar

Or maybe add configuration in the config/views.php.

TaylorOtwell's avatar

Just following up on this. If you are using 4.3 / 5.0 already and want to use the old Blade tag behavior, you should actually do this:

Blade::setEchoFormat('%s');
1 like
TaylorOtwell's avatar

@thepsion5 - I actually didn't go with that syntax for the very reason you stated. It blends in with the other Blade syntax for "echo" too much. I wanted something that stands in stark contrast to most other Blade echos so that it is visually obvious you are echoing un-escaped text.

1 like
isimmons's avatar

Thanks for the answer @TaylorOtwell

Well I had been using setContentTags to reverse the two tag types because it comes natural to quickly do {{}}. I'm glad that is escaped by default now. I was using {{{}}} for raw content which in my mind is visually obviously different than {{}} but I can see where looking over code quickly, it could get missed. Just have to get my pinky finger used to reaching for that '!' :-)

yunusis's avatar

Too bad Phpstorm just included support for blade syntax. So will have to use Blade::setRawTags($openTag, $closeTag) for now unless they add an option to change that.

cooldot's avatar

One thing that puzzles me, well, a few things puzzle me actually, but I'll try and keep this on topic :)

"I actually didn't go with that syntax" - but you did, didn't you? Which is why so many people will now have to either change lots of code when converting to 5 or use setRawTags to make things work the way they used to (the way they invested their time and effort into).

If it is so easy to change back to using {{ }} (or to change to what ever we prefer to use) with one simple command, then where is the argument for changing what was the default in the first place? Why not just publicise the setRawTags function instead? Which is essentially what's happening here any way.

Assuming someone does use setRawTags, will this remain compatible in the future, or should we be expecting 'trouble'? :)

Okay, now I just saw the Blade::setEchoFormat('%s'); post. So we use this instead?

I guess most of these questions are also applicable for HTML / Form as well.

2 likes
imade's avatar

I agree with thepsion5. I would prefer {{! foo() !}} or {{!! foo() }} as it would be more easy to type (brackets auto-close, exclamation marks are quire a stretch). But maybe it's just something to get used to. Overall I'm a big fan off all the 5.0 changes!!

afrayedknot's avatar

@cooldot - "If it is so easy to change back to using {{ }} (or to change to what ever we prefer to use) with one simple command, then where is the argument for changing what was the default in the first place?"

The argument is that XSS attacks are the 3rd biggest security issues facing websites today: https://www.owasp.org/index.php/Top_10_2013-A3-Cross-Site_Scripting_(XSS)

By setting the default behaviour to protect against XSS attacks - you help ensure an improved compliance with the security requirements, and the framework helps people towards 'best practice'.

It wont solve the problem overnight - but there will now be less web applications that are susceptible to XSS attacks.

Next

Please or to participate in this conversation.