I try to echo a page title by doing a page validation (with $id being the page id): <?php e($site->find($id), $site->find($id)->title(), "No title") ?>
Expected behaviour :
I am checking if the page exists. If it exists then echo the page title. If not echo “No title”.
Current behaviour:
If the page does not exist the kirby debugger throws: Call to a member function title() on null
If I do the page validation with a classic if-else condition I get the expected behaviour.
Can anyone explain why?
The reason why this is happening it’s because (I think) Kirby tries to execute this part of the code $site->find($id)->title() no matter what the initial condition ($site->find($id)) returns.
In a traditional if/else situation that part is skipped entirely which is why you get your intended behaviour.
You can probably replace it with a ternary statement like this one (untested but you get the overall idea)
<?= ($yourPage = $site->find($id)) ? $yourPage->title() : "No title" ?>
Yes, that is true, because this bit is passed as a function parameter, so the parameter is actually executed, independently of the condition, because the condition itself is only evaluated inside the function. That means you have to pass valid parameters.
Isn’t this a syntax issue? I’m no PHP programmer, but using <?php instead of <?= when “evaluating & spitting-out” has caused similar issues for me in the past. Using the latter may solve part of this. I hope this is helpful.
No, that’s not the issue here. The e() helper actually echos something, so you would use <?php e() ?>, not <?= e()?>, because <?= is short for <?php echo`.
When I first encountered the e() helper and its description as a “Smart version of echo with an if condition as first argument”, I had the same intuition: I imagined some added functionality beyond being a ternary statement wrapper.
I think there would be value in having a “smart version of echo” that specifically catches the case of an invalid parameter in the function and treats it as a “false”; it would simplify working with such if-conditions in templates. The e()-helper could internally check that the parameter is valid before handing it on to r() (which is a ternary statement) and “fail silently” if it is not.
Is this something worth suggesting on the ideas repo, or am I overseeing some technical or dogmatic (the helper would essentially have to contain a catch for the error condition) limitation here?
For me there would be definitely value of having a real “smart version of echo”.
When I look at my code right now, the el-classico if-else-statements and ternary statements (where possible) are the main chunk of my php-code.
By the way: the r() helper fails with my example either.
Yes, I played around with that idea I outlined above (tried to write my own e2() helper), and eventually finally understood what you had said earlier about PHP functions in general:
Please disregard my brainstorming above, I had something in mind that is indeed technically impossible Ternary operators it is… (but this helped me to finally understand why sometimes e() fails while if-else works!)
I would have expected the behaviour I described on my initial question: the e() helper only runs into the true value when the condition is true, without testing the true value itself. But I get your and @texnixe point that this is technically not possible.
So for me this issue is closed with the words “Hooray ternary statements!”
I don’t think there’s a holy grail function we can use here (unfortunately)
I personally use a bunch of different methods depending on what I’m doing.
There’s the or() method that is sometimes useful $page->somefield()->or($page->fallback())
There’s also the ?? operator that is also useful in some cases <?= $page->somefield() ?? $page->fallback()
Another option is to check if the page I need to use exists before I do anything else (useful depending on how the template is structured). For example, if I’m in a snippet and I’m printing content that’s tied to a specific page I usually check if the page exists at the beginning of the snippet and return if the page is not there.
Anyway, useful discussion and glad @Mattrushka got an answer