We have objects that implement __toString()
:
class Foo {
public function __toString()
{
return 'bar';
}
}
Then we have functions that return either string
or object that implement __toString()
, like the example above.
While using return type string
for strings works of course:
function getString():string {
return 'Works!';
}
Returning object of type Foo
does not work, because it's not a string
:
function getString(Foo $foo):string {
return $foo; // Fatal TypeError!
}
Is there any PHP interface that we can use to type hint both string
and objects that implement that unknown interface, e.g. Printable
or Stringable
(lol)?
The goal is to being able to return either string
or objects that implement a specific interface (which would enforce the implementation of __toString
).
The simple answer is "no" - there is no built-in "stringable" hint, although it has occasionally been suggested in the past.
As of PHP 8.0, there will be support for "union types", so string|Stringable
would represent "either a string
or an instanceof Stringable
". However, there's no such interface as Stringable
, so this can't be used to detect implementations of __toString
.
Part of the reason for this, and the design question you need to ask, is what contract are you actually representing here? From the point of view of the calling code, there is no guarantee that the return value can actually be used as a string directly - there are many operations which will behave differently for a string and an object, or which will accept a string but not cast an object automatically. So the only thing that's actually guaranteed by such a hint is that (string)$foo
will give a string.
So you have a few options:
Stringable
. If the function wants to return a string, it would first wrap it in a simple object.Stringable
, come up with a more meaningful interface to return; maybe what you actually return is something Loggable
, for instance. This way, wrapping the string can give you more concrete benefits: you can add other methods to the interface, and the calling code doesn't need to do an "object or string" check before calling those methods.string
, and cast any objects to string before returning them.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With