14

I am using PHP 7.4 for a laravel application and I am getting this exception very frequently.

ErrorException (E_DEPRECATED)
Unparenthesized `a ? b : c ? d : e` is deprecated. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)`

The code which triggers this exception is :

foreach ($allLanguages as $languageKey) {
    $original[$languageKey] =
        isset($values[$languageKey])
            ? $values[$languageKey]
            : isset($filesContent[$fileName][$languageKey][$key]) ? $filesContent[$fileName][$languageKey][$key] : '';
}

Can any help me to resolve this issue?

Found that this is E_DEPRECATED error due to some upgrade in PHP, but is there any way to resolve this exception by converting the deprecated code to latest?

Paulo Boaventura
  • 1,365
  • 1
  • 9
  • 29
humbleiam
  • 969
  • 2
  • 12
  • 34

3 Answers3

12

You need to add parentheses around your code:

Before:

$reference->frotel_vitrine = empty($item->special) ? null : $item->special == 2 || $item->special == 3 ? 'active' : 'deactivate';

After :

$reference->frotel_vitrine = empty($item->special) ? null : (($item->special == 2 || $item->special == 3 )? 'active' : 'deactivate');

That should solve the issue.

Alex
  • 878
  • 3
  • 16
  • 34
Amirex
  • 241
  • 3
  • 9
10

This change in php has been done to remove ambiguity in the decision tree so that there is an explicit order of condition execution.

The deprecation warning is reproduced here:

Code:

$allLanguages = ['en', 'es', 'fr'];
$values = ['es' => 'Spanish1'];
$filesContent = [
    'foo' => [
        'es' => ['bar' => 'Spanish2'],
        'fr' => ['bar' => 'French']
    ]
];
$fileName = 'foo';
$key = 'bar';

$original = [];
foreach ($allLanguages as $languageKey) {
    $original[$languageKey] =
        isset($values[$languageKey])
            ? $values[$languageKey]
            : isset($filesContent[$fileName][$languageKey][$key])
                ? $filesContent[$fileName][$languageKey][$key]
                : '';
}
var_export($original);

Output:

Deprecated: Unparenthesized `a ? b : c ? d : e` is deprecated. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)` in /in/TG4g2 on line 17
array (
  'en' => '',
  'es' => 'Spanish2',
  'fr' => 'French',
)

As a human-reader of your script, I would assume the reading of your condition as left to right -- but this would place Spanish1 as the output value.

Even before php7.4, the output isSpanish2 because the latter fork in the decision tree is given precedence.

To avoid this, you must wrap your conditions in parentheses to dictate exactly how the order of execution should be handled.

Also, I agree with @Laurel that in php7 it is time for you to embrace the syntactic sugary sweetness that is the null coalescing operator. This will avoid precedence issues and the need to use parentheses, but depending on your desired results, you may need to reorder your conditions.

Priority to $values: (Demo)

$original[$languageKey] =
    $values[$languageKey]
        ?? $filesContent[$fileName][$languageKey][$key]
            ?? '';

Priority to $filesContent: (Demo)

$original[$languageKey] =
    $filesContent[$fileName][$languageKey][$key]
        ?? $values[$languageKey]
            ?? '';

P.s. IIRC, the php manual advises against the use of nested ternaries/conditionals like this on the basis of code clarity. I don't mind this scenario and I like the avoidance of code bloat, but other devs may take a more purist stance.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • It is showing the deprecated but how can we know when it will give the fatal error so we can give some time to correct that code before the specific date? – Bhavin Thummar Feb 09 '21 at 06:00
  • "_It is showing the deprecated_" ...then the time to start fixing your project is: now. – mickmackusa Feb 09 '21 at 06:09
  • Thakns for the answer. Do you know which php version is generated this warning? – Bhavin Thummar Feb 09 '21 at 06:20
  • Deprecated from PHP7.4 and fatal from PHP8. https://3v4l.org/TG4g2 – mickmackusa Feb 09 '21 at 06:32
  • @Ahmad We should always welcome language refinements that remove ambiguity/confusion. – mickmackusa May 25 '21 at 01:18
  • @mickmackusa do you know how to resolve this below $d = $a ? $d : ("'" === $d[0]) ? $d : "'" . $d . "'"; which is showing the same error on PHP 8. PHP Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)` – Naveenbos Mar 09 '22 at 16:28
  • 1
    `$d = $a ? $d : ("'" === $d[0] ? $d : "'$d'");` @Nav – mickmackusa Mar 09 '22 at 21:27
3

In your case, you should use ?? instead of isset and ternaries:

foreach ($allLanguages as $languageKey) {
    $original[$languageKey] = $values[$languageKey]??  $filesContent[$fileName][$languageKey][$key] ?? '';
}

Laurel
  • 5,965
  • 14
  • 31
  • 57