-
Notifications
You must be signed in to change notification settings - Fork 0
add optional() helper #587
Comments
+100 i also need it very often in Kirby 👍 |
@bnomei But it will not work. In Kirby, we access the properties by method. And if the method returns For example; if It could be like with direct access to property, i guess it's not possible either echo optional($page->image->first)->html(); |
@afbora i think thats the point of the helper...
|
If I don't miss anything I think it's pretty easy to implement. class NullObject
{
public function __get()
{
return null;
}
public function __call()
{
return null;
}
public function __toString()
{
return '';
}
}
function optional($object)
{
return $object ?? new NullObject();
} |
I don't think the field method is possible though |
@bnomei Yes it is true, but if this is the last method called, it works. Otherwise you get:
Works only $page is not null:
Will not work if page has not an image:
Sent to the optional function after the parameter run. |
We are experiencing the same issue for the |
I'm not sure, but maybe it can be resolved by creating an $page->image()->optional('first.html'); |
Thinking of the field method, could you swap positions? Like |
Then each field method has to provide If one of them returns $page->optional()->image()->other()->methods();
^^^^^^ think image() is null I don't know if it is possible but maybe if the |
Hmmm, that's interesting. This would be a great solution if we could wait until the last method in the chain is called and then react on that method call. But as far as I know that's not possible in PHP. |
Thinking out loud: each method knows about the page context, doesn't it? So couldn't the |
I've few tests and possible with fake field that I'm sure @lukasbestle has an idea for this. |
I have not tested this with real code yet, but I think I know how to solve this in PHP using a proxy object. The syntax would look like this: optional($page)->images()->first()->other()->methods()->resolve(); and/or: $page->optional()->images()->first()->other()->methods()->resolve(); What the helper and method would do is the following:
There is indeed no way to do this without a final method call that converts the proxy object back to the underlying value. So the Do you think this would be acceptable? If so, I can prepare a PR. |
@lukasbestle I liked the proxy design pattern idea. Can't we do what the resolve method does with the magic methods inside the proxy object? 🤔 then it would be great. |
The magic We can use the magic |
So can we use the resolve method as a fallback?
|
Yes, that would work! |
to avoid introducing a new method called there is a fallback field method called $page->optional()->images()->first()->url()->or(asset('images/placeholder.png'));
$page->optional()->images()->first()->url()->or(); // => null |
I like the simplicity of this! To make sure we don't get each other wrong: When calling But in any case, I like the simple name (much better than Another alternative would be to provide a helper that would need to be used to end the chain if string conversion with the magic $optional = $page->optional()->images()->first()->url();
resolve($optional, 'default value');
or($optional, 'default value'); Advantage: No method name is blocked. Disadvantage: Much less convenient. |
i would be fine with just the helper... the main selling point is that $url = optional($page->optional()->images()->first()->url(), site()->url()); maybe we can make both params of optional also accept closures not just a proxy object? it would be more in line with the $url = optional(
option('myplugin.callback'), // from plugin options
function () use ($myvar) { // or plain php
return $myvar;
}
); |
What do you mean with "resolving field method"?
Hm, now that I think about it: The existing |
using |
r($condition, $a, $b);
optional($a, $b);
r($a, $b); // would evaluate $a as condition edited: ah... you meant using $condition as $a and $a as $b if $condiction is a proxy. |
Unfortunately this syntax won't work. We need some way (helper or page method) to initiate the proxy, so it would need to be one of these: optional($page->optional()->whatever()->nullHere()->chain(), 'fallback');
optional(optional($page->whatever()->nullHere()->chain()), 'fallback');
Yes, something along these lines. We would have to see if this is viable, but we can only tell if we actually implement it. |
laravel has it and could be useful in kirby as well.
https://laravel.com/docs/7.x/helpers#method-optional
example in kirby
not sure how its implemented in laravel and if it can be used for field methods but i would still like to see the helper in general.
The text was updated successfully, but these errors were encountered: