PHP 8.0: New Stringable
interface
PHP 8.0 adds a new interface named Stringable
, that indicates any classes implementing the Stringable
interface implement a __toString(): string
magic method.
To provide forward compatibility, PHP engine automatically adds the Stringable
interface to all classes that implement a __toString()
method.
interface Stringable {
public function __toString(): string;
}
The most common use case would be a strict type inside a function/method before it attempts to use a string function.
class Foo {
public function __toString(): string {
return 'FooBar';
}
}
function safePrint(string|Stringable $input): void {
echo htmlspecialchars((string) $input);
}
The safePrint
function can use Union Types to indicate and enforce that it accepts scalar string
types, or an object of a class that implements Stringable
interface.
Optional to declare implements \Stringable
If a class implements a __toString
method, PHP automatically considers that it implements the Stringable
interface. It is not required, but possible to explicitly declare it.
class Foo implements \Stringable{
public function __toString(): string {
return 'FooBar';
}
}
Checking string capabilities
With both scalar string
type and the new Stringable
interface, it is now possible to safely use string functions in an application that types are enforced.
$foo instanceof \Stringable
instanceof
checks will return true
for classes that implement __toString
method with or without explicit implements \Stringable
declaration.
class Foo {
public function __toString(): string {
return 'FooBar';
}
}
$foo = new Foo();
var_dump($foo instanceof Stringable); // true
Note that instanceof
currently requires an object, and does not accept scalar variables yet.
class_implements($foo)
class_implements
function will correctly return that a given object from a class that has a __toString()
method with or without an explicit implements \Stringable
declaration will return Stringable
as one of the interfaces the class implements.
class Foo {
public function __toString(): string {
return 'FooBar';
}
}
var_dump(class_implements(new Foo()));
// array("Stringable" => "Stringable")
is_string($foo)
The is_string
function checks the type of the variable and return true
only if the type of the parameter provided is string
. Because objects from classes that implement __toString
are objects, is_string()
function returns false
on objects even if they comply with Stringable
interface with or without explicit declaration.
class Foo {
public function __toString(): string {
return 'FooBar';
}
}
var_dump(is_string(new Foo())); // false
strict_types = 1
behavior
Stringable
objects will be evaluated to strings with __toString
when strict types are not enforced. If strict typing is enforced (with declare(strict_types=1)
at the top of the file), an explicit string cast is required.
declare(strict_types=1);
class Foo {
public function __toString(): string {
return 'FooBar';
}
}
function safePrint(string|Stringable $input): void {
echo htmlspecialchars($input);
//^^^ No string cast
}
safePrint(new Foo());
// Fatal error: Uncaught TypeError: htmlspecialchars(): Argument #1 ($string) must be of type string, Foo given in ...:...
In the snippet above, strict types are enforced. htmlspecialchars
function only accepts string
parameters. In case an object of Stringable
interface is passed, PHP will refuse to accept it even though the object implements Stringable
interface.
When strict types are enabled, make sure to cast
string|Stringable
values to strings with(string) $input
.
Backwards Compatibility Impact
It is trivial to bring the new Stringable
interface to PHP versions prior to 8.0. However, note that unless the class explicitly declares implements \Stringable
, PHP versions prior to 8.0 will not provide the string-capability checks as mentioned above.
interface Stringable {
public function __toString(): string;
}
class MyStringCapableClass implements Stringable {
public function __toString(): string {
return 'Hello World';
}
}
For the compatibility for prior PHP versions, the Stringable
class must be added, and all classes providing string capabilities must explicitly declare that they implements \Stringable
.
Related Changes
- Class magic method signatures are strictly enforced
- Union Types
- Locale-independent
flaot
tostring
casting - New
mixed
pseudo type