When working with Eloquent: API Resources, mergeWhen() is trying to execute the enclosed statement. Which defeats the ability to merge conditional attributes, when an 'attribute' is the condition.
unset variables.$this->mergeWhen(Auth::user()->isAdmin(), ['this is executed for nonAdmin users too']);
Below are two (2) examples.
return [
'href' => $this->href,
'validFor' => [
'startDateTime' => $this->created_at->toDateTimeString(),
$this->mergeWhen(false, [
'endDateTime' => $this->deleted_at->toDateTimeString(),
]),
],
];
unset($foo); // isset($foo) = false
return [
'a' => 'b',
'c' => 'e',
$this->mergeWhen(isset($foo), [
'f' => $foo,
]),
];
I don't really get where you're going with this. Obviously the code in your examples is executed. That's just how PHP works.
Underneath it uses the value helper so you can use a closure instead to delay the execution:
return [
'href' => $this->href,
'validFor' => [
'startDateTime' => $this->created_at->toDateTimeString(),
$this->mergeWhen(false, function () {
return [
'endDateTime' => $this->deleted_at->toDateTimeString(),
];
}),
],
];
I would expect that a enclosed statement (technically it's the second parameter) is ONLY executed when the condition is met. That's how PHP is normally works. That's how conditional statements are supposed to work. mergeWhen() appears to be a conditional function.
unset($foo);
if (isset($foo)) {
echo "PHP does NOT execute this line";
}
if (false) {
echo "PHP would NOT execute this line either";
}
Using an enclosure does solve the issue. Thanks! It resolves the issue for me.
But... Since mergeWhen() appears to be a conditional function:
closure be the default?false condition does not prevent evaluation of the second parameter? // forgive the incorrect semantics, trying to make a point here
if (false, function() {
echo "You're telling me to prevent execution of these lines..";
echo "that I should change how the conditional function is written.";
}); // If I found that if() did not work as expected, I would have to add a closure?
There's also the security concern. While I doubt the risk is high due to applicable uses ofmergeWhen() But as a conditional, the expected default behavior of mergeWhen() is it would not execute $this->is->dangerous() in the code below.
$admin = false;
//
$this->mergeWhen($admin, [
'dangerous' => $this->is->dangerous(),
]),
//
@poing I think you're simply misunderstanding how code execution in PHP works. The way it's compiled is that any code that's being passed as a parameter is executed before it's passed through the argument. A closure based approach like I've shown above prevents this.
@driesvints Nah, I get it. It's the parameter that's being evaluated. The enclosure let's the parameter pass, where it's not evaluated unless true in the function.
I want to merge an array that uses many variables. Do I really have to pass them all into the closure with a use statement?
Most helpful comment
I don't really get where you're going with this. Obviously the code in your examples is executed. That's just how PHP works.
Underneath it uses the
valuehelper so you can use a closure instead to delay the execution: