Closed DfKimera closed 6 years ago
I thought we removed (or deprecated) the Blade 'or'?
@browner12 Apparently not, compileEchoDefaults()
is still called for every echo type.
This regex might work instead:
public function compileEchoDefaults($value)
{
return preg_replace('/^(?=\$)(^[^\'"]+)(?:\s+or\s+)(.+?)$/si', 'isset($1) ? $1 : $2', $value);
}
assign the string to a variable. This has surfaced several times and @themsaid has mentioned it was probably a 'no-fix'. see #17934
Let's deprecate the 'or' functionality then in 5.6, and remove in 5.7.
@Nathanw It misses some edge cases, like $arr["lorem ipsum?"] or "dolor"
.
I've just pushed a PR that accounts for those, feel free to point out any mistakes or things I may have missed.
@devcircus @browner12 I think it's worth a fix, it's a very handy feature and it breaks on code that's much simpler than #17934. One less thing to put in the migration guide (and replacing a couple hundred instances of these in existing views would be hell!)
go ahead and fix it in 5.6, but I'm going to put a PR into 5.7 to remove it. It's a regex nightmare, and it's equally solved by the null coalesce operator (??
) in PHP 7, that we now require.
the find and replace in your views is not that bad. I did it preemptively on a pretty large project a couple versions back, and it only took me about 10 minutes at most.
It's simply not possible to use regex to parse this because it's not a regular language. Most of blade ultimately falls fowl to this, though we can do well in practice by limiting ourselves to finite nesting. One can show that we cannot recognise the infinite langauge of only correctly nested turnaries using the pumping lemma. This is because this language is context free.
@browner12 Agreed, with ??
the or
keyword becomes redundant. I pushed #23530 for 5.6, can you take a look?
Description:
When outputting the result of a ternary operation using Blade, and the string contains the
or
keyword, the parser incorrectly identifies it as being a Blade-style ternary operator ({{$variable or 'not defined'}}
).What happens is the contents of the
or
in the string gets replaced with the ternary macro (isset($variable) ? $variable : 'not defined'
), breaking the output code.Here's an example of the affected code:
Here's the Whoops screenshot showing the incorrect replacement.
If I surround the
$variable
with parenthesis, the parser does not kick in. (eg:{{ ($variable) ? 'lorem or ipsum' : 'dolor' }}
)Steps To Reproduce:
On a clean Laravel project, add the following string to
welcome.blade.php
:Fixing the issue:
The RegExp that is failing is here:
https://github.com/laravel/framework/blob/90fc0babe1c854249c1750be9dfc6ab8f0937935/src/Illuminate/View/Compilers/Concerns/CompilesEchos.php#L101-L104
I believe
(.+?)
is incorrectly matching?
, which would signal the end of the variable/property name and indicate a ternary expression. There's probably a few other edge cases that break (since the feature is meant to also match things like$obj->property
and$arr['key']
, so it's very permissive).I'm not very good with RegExp, so I haven't thought of a fix yet, but I'm willing to dig deeper if no one has a quick fix in mind.