FFS. I'm part way through an article on something completely unrelated, and needed to knock up some code to demonstrate PHP's "magic"
__toString()
method. That code worked fine, but my sample code cacked-out because bloody PHP still can't deal with unexpected error conditions coherently.So here's something about
__toString()
, and something about PHP being f***in' stupid.PHP's
__toString()
method is something one can put into a class so what if an object of that class is ever used as a string, then __toString()
will be called, and if it returns a string, that string will be used. Fairly obvious stuff really. I wish CFML had this (I think Lucee kinda might? But ColdFusion does not). Anyhow, here's an example:<?php
// classWithToString.php
require __DIR__ . "/safeRun.php";
class Person{
protected $name;
function __construct($name){
$this->name = $name;
}
}
class StringablePerson extends Person {
function __toString(){
return $this->name;
}
}
safeRun("Outputing a Person", function(){
$son = new Person("Zachary");
echo "The boy's name is $son<br>";
});
safeRun("Outputing a StringablePerson", function(){
$son = new StringablePerson("Zachary");
echo "The boy's name is $son<br>";
});
Here I've got a Person class which has no special treatment of string-conversion, and a subclass of that which provides a
__toString()
implementation.Ignoring what
safeRun()
is supposed to do for a second, we can see what happens if we try to use a Person as a string:
Outputting a Person
Catchable fatal error: Object of class Person could not be converted to string in D:\src\php\php.local\www\experiment\7\types\classWithToString.php on line 25
Fair enough. Now... using a StringablePerson:
Outputing a StringablePerson
The boy's name is Zachary
Ran OK
So that demonstrates
__toString()
(superficially). All good.Now back to what
safeRun()
is supposed to add to this mix. Let's look at it:// safeRun.php
function safeRun($message="", $task){
echo $message . "<br>";
try {
$task();
echo "Ran OK<br>";
}catch (Throwable $t){
printf("Code: %s<br>", $t->getCode());
printf("Message: %s<br>", $t->getMessage());
}finally {
echo "<hr>";
}
}
Note how it's expecting error conditions to arise. It's catching all Throwables. So how - the f*** - come that first example still spews out:
Catchable fatal error: blah blah blah blah blah
FFS, PHP.
- A type-check failure is not a "fatal error" in any sense of what a fatal error might be. It's just a bloody type-check failure, which should be an Exception.
- Errors are sub-classes of Throwables, so I should still be able to catch it!
- Especially one that self-describes as being catchable. The hint is in the name.
I've been around the houses with this stupidity already ("PHP 7: PHP starts to play catch-up with error- / exception-handling", "PHP 7: alpha 2 breaks EngineExceptions (on purpose, as it turns out)"), and I'm getting sick of it. I can only presume there's yet a third type of error situation that needs special catching treatment: something that is not an Exception or Error (both Throwables), but is something else again. Get yer heads out of yer arses, PHP.
And now I won't have time to finish my other article this morning before I start work, as I've been pantsing around with this sh!t for the last half hour.
It's nice to start the day in a good mood. So I'm told. [wipes froth from mouth]
--
Adam