This is an old revision of the document!
PHP RFC: Add Stringable interface
- Version: 0.9
- Date: 2020-01-15
- Author: Nicolas Grekas, nicolas.grekas+php@gmail.com
- Status: Draft
- First Published at: http://wiki.php.net/rfc/stringable
Introduction
This PR introduces a new Stringable interface that can be added to implementations of the __toString()
method.
It has two goals:
- allow using
string|Stringable
to expressstring | object-with-__toString()
- provide a forward upgrade path from PHP 7 to 8
Proposal
This goal is to allow using the string|Stringable union type in PHP 8, to accept both strings and objects that implement __toString()
and declare this interface. This is critically missing currently, on codes that deal with stringable objects: they can't be made type-safe.
On purpose, there is no corresponding is_stringable()
function, because that would require defining what happens when e.g. an int is passed to this function, and there are no simple answers to this concern.
On purpose also, for BC, classes that implement __toString()
aren't required to declare the interface.
Such classes wouldn't pass the above union type, but that's expected, as that's the semantics of the language.
By being simple and without any magic capabilities on its own, this interface is trivially polyfilled on PHP < 8.
Once a polyfill becomes widely available (I would personally add one to symfony/polyfill-php80 immediately after this PR is accepted), I expect code style checkers to be able to enforce declaring the interface when __toString()
is used. For projects that don't use cs checkers, they'll notice quickly that they missed adding the interface because their users will ask for it when they'll want to pass the string|Stringable
union type.
Here is the stub declaration of the interface:
interface Stringable { public function __toString(): string; }
Because it adds the string
return type, this interface has the potential to force a BC break on any existing libraries that want to adopt it.
In order to ease forward and backward compatibility, the PR also adds the return type to existing __toString()
methods when it's not explicitly declared already. Returning a string is already enforced by the engine so this doesn't change any semantics.
This way, code moving to PHP8 won't be forced to add the return type explicitly (which would break BC on their side), and code in PHP < 8 can adopt a polyfill interface immediately (one that doesn't declare the return type for the same BC reasons.) Providing an easy forward-path is the second goal of this PR.
For reference, here are some annotations in Symfony, added by contributions from real-world use cases and that currently cannot be expressed precisely enough using any union types in PHP 8.
Backward Incompatible Changes
Code that declare a symbol named Stringable
in the root namespace will have to rename it.
Proposed PHP Version(s)
PHP 8.0
RFC Impact
To Existing Extensions
Extensions will need to add the string
return type when they declare __toString()
methods.
Open Issues
Make sure there are no open issues when the vote starts!
Unaffected PHP Functionality
List existing areas/features of PHP that will not be changed by the RFC.
This helps avoid any ambiguity, shows that you have thought deeply about the RFC's impact, and helps reduces mail list noise.
Future Scope
This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC.
Proposed Voting Choices
Accept the proposed interface: yes/no
Patches and Tests
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
- a link to the language specification section (if any)
References
Rejected Features
Keep this updated with features that were discussed on the mail lists.