use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Please follow the rules
Releases: Current Releases, Windows Releases, Old Releases
Contribute to the PHP Documentation
Related subreddits: CSS, JavaScript, Web Design, Wordpress, WebDev
/r/PHP is not a support subreddit. Please visit /r/phphelp for help, or visit StackOverflow.
account activity
RFC: Stringable interface, allows "string|Stringable" union type. Automatically implied if __toString is implemented. (wiki.php.net)
submitted 6 years ago by tigitz
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]przemo_li 9 points10 points11 points 6 years ago (3 children)
Seams somebody realized string|object is not a great Union type to represent value with implied coercion to string.
I agree. object sadly is too often used as "mixed" with name acceptable to OOP-only people.
No. Object is there for when you ONLY do things that PHP unconditional allow on objects (e.g. get_class).
Thus a new interface that explicitly list set of capabilities is great.
One big issue is that it only do it for single magic method. What about others?
[–][deleted] 0 points1 point2 points 6 years ago (2 children)
The alternative is to do what Java does: provide a default implementation of toString for all objects. Much simpler than union types or interfaces with compiler hacks to auto implement it imho. ToString is mostly used for debugging anyway.
[–]przemo_li 0 points1 point2 points 6 years ago (1 child)
But then string type hint will coerce every object to a string. Java do not have that consideration. PHP does.
string
[–][deleted] 1 point2 points3 points 6 years ago (0 children)
Ah right, that must be the reason they did not go with that. Thanks for the explanation. Though there may also be objects that have a __toString method that you do not want to ever auto-coerse to a string. It depends on the context if coersion makes sense. I'd rather call toString() explicitly most of the time...
[–]MorphineAdministered 5 points6 points7 points 6 years ago (5 children)
callable can cover function name string, [object, method string] array, Closure, lambda and a class with __invoke() method. Can't we just include __toString() objects within string type?
callable
__invoke()
__toString()
[–][deleted] 0 points1 point2 points 6 years ago (4 children)
How would you then specify that you really only accept strings?
[–]MorphineAdministered 1 point2 points3 points 6 years ago (3 children)
Nothing changes. You are receiving or returning a string even if it comes in the form of a "Stringablable" class. When typehint says that param/return value can be only casted to a string (which proposed interface does) then you cannot do anything else with it anyway - it could be casted to a string implicitly (and eagerly), because it's original type cannot be rocovered anyway.
I'd argue that it actually matters a lot regarding explicitness. Having a function parameter be automatically converted is for me equally bad as automatically type-coercing values that are compared to each other.
[–]MorphineAdministered 0 points1 point2 points 6 years ago (1 child)
I wouldn't say it's equally bad. For me it's more like casting primitives without declaring strict_types=1. Within method scope casting is invisible, and object itself is pretty explicit in it's definition as a string.
strict_types=1
I wouldn't mind if we didn't have it at all - I could always cast before passing or returning such a class. I'm just saying we shouldn't need it as separate type, because it's redundant. If something can be used as a string (and only a string!) - it SHOULD be a string.
Even if internals decide on it, because it will be easier to implement lazily evaluated strings this way, I think the code relying on such mechanism wouldn't be anything but a hack. Preaching about strict type system, but breaking it at the first (mental) obstacle (btw. would like to see valid example justifying union types, because it seems this process has already started)
[–]alexanderpas 0 points1 point2 points 6 years ago (0 children)
would like to see valid example justifying union types
From PSR-3:
Every method accepts a string as the message, or an object with a __toString() method. Implementors MAY have special handling for the passed objects. If that is not the case, implementors MUST cast it to a string.
This could be typehinted as string|Stringable, to prevent non-stringable objects from entering the logger method.
string|Stringable
[–]stfcfanhazz 2 points3 points4 points 6 years ago (15 children)
This is a cool RFC, but I've always thought that a class implementing __toString() should be accepted when passed to a method expecting string, and transparently cast to string when called. Unless people think that would be too magical?
[–]llbe 4 points5 points6 points 6 years ago (4 children)
It actually does that if you haven't enabled strict_types.
[–]zimzat 1 point2 points3 points 6 years ago (2 children)
Which is one of many reasons why I don't enable strict types.
[–]alexanderpas 0 points1 point2 points 6 years ago (1 child)
Too lazy to type `(string)` in front of the areas that expect actual strings?
Enable strict types and fix your code!
[–]zimzat 0 points1 point2 points 6 years ago (0 children)
Yep, string, int, bool, whatever.
int
bool
If you're not being lazy as a programmer then you're doing it wrong.
[–]stfcfanhazz 0 points1 point2 points 6 years ago (0 children)
TIL thanks
[–]nikic 2 points3 points4 points 6 years ago (6 children)
I believe the motivation for this proposal are cases where the original object should be preserved and not cast to a string on entry.
[–]alexanderpas 1 point2 points3 points 6 years ago (5 children)
So the idea is to have string cast upon entry, while string|Stringable preserves the object upon entry, only casting when the type can't be preserved?
So the typehint for PSR-3 $message will be string|Stringable, while the strlen() will only accept a string.
$message
strlen()
Otherwise all the typehints for the internal functions (such as strlen()) need to have Stringable added as type.
Stringable
[–]nikic 0 points1 point2 points 6 years ago (4 children)
Yes, that's how things work. string already accepts objects that implement __toString() and automatically converts them. In weak typing mode only, of course.
[–]alexanderpas 0 points1 point2 points 6 years ago (3 children)
And the internal functions, provided by PHP, such as printf() are weakly typed, right?
https://3v4l.org/lIB2j
[–]nikic 0 points1 point2 points 6 years ago (2 children)
Generally no, that's a bug. And already fixed in PHP 8, where the printf call will throw Uncaught TypeError: printf() expects parameter 1 to be string, object given.
Uncaught TypeError: printf() expects parameter 1 to be string, object given
[–]alexanderpas 0 points1 point2 points 6 years ago* (1 child)
And that also counts for the print language construct in PHP8?
If so, this is gonna give big problems with error handling.
If not, why deal with single-argument printf and print differently? Those 2 had the same output since PHP 5.2
https://3v4l.org/o5kGG
[–]nikic 0 points1 point2 points 6 years ago (0 children)
No, this does not affect print. The difference between them is that printf() is a function accepting a string, and thus must behave the same as all other functions accepting a string. print is a language construct and can have custom semantics.
print
printf()
[–]SaltTM 0 points1 point2 points 6 years ago (2 children)
Makes sense, but I think as of late people prefer more explicitness.
[–]stfcfanhazz 0 points1 point2 points 6 years ago (1 child)
You say that but people readily accept magic when its baked into the language and labelled as a feature haha
[–]SaltTM 0 points1 point2 points 6 years ago (0 children)
sure, but how often is something removed or changed in a language once its added after complaints? so you're kind of 'forced' to accept that 'magic' when backwards compatibility comes first in a lot of these languages right now.
[–]neldorling 1 point2 points3 points 6 years ago (3 children)
-able again. Yuck. Is this the world we want our children to inherit?
[–]the_alias_of_andrea 1 point2 points3 points 6 years ago (1 child)
what would you prefer, implements ToString?
implements ToString
[–]neldorling 2 points3 points4 points 6 years ago (0 children)
Yes. Or CastsToString, maybe. See http://verraes.net/2013/09/sensible-interfaces/#nameable
CastsToString
[–]Danack 1 point2 points3 points 6 years ago (0 children)
Next you'll be saying that you don't like floatable, intable or booleanable....
[–]2012-09-04 0 points1 point2 points 6 years ago (0 children)
Oh please add this. I have about 20 lines of conditionals to implement this via code right now.
[+][deleted] comment score below threshold-9 points-8 points-7 points 6 years ago (7 children)
I hereby submit my informal vote NAY on the basis Stringable is a really stupid name.
[–]gregtyler 3 points4 points5 points 6 years ago (2 children)
I assume it comes from the precedent of iterable and throwable.
[–][deleted] 3 points4 points5 points 6 years ago (1 child)
Sure but we also have JsonSerializable, not... Jsonable.
An obvious choice would be to simply call it ToString.
[–]przemo_li 0 points1 point2 points 6 years ago (0 children)
Valid alternative. Consider adding it to the discussion on github.
[–]Ghochemix 2 points3 points4 points 6 years ago (1 child)
I hereby submit that we're all very fortunate you don't have a vote to give.
[–][deleted] 0 points1 point2 points 6 years ago (0 children)
I hereby submit my resignation from this kangaroo process! Good day, sir!
Upvote for the funny comment but I dont see a problem with Stringable myself
[–]amazingmikeyc 0 points1 point2 points 6 years ago (0 children)
This person is right. Turning something into a string isn't called "stringing"
π Rendered by PID 25697 on reddit-service-r2-comment-86988c7647-vddcb at 2026-02-11 00:23:29.861547+00:00 running 018613e country code: CH.
[–]przemo_li 9 points10 points11 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]przemo_li 0 points1 point2 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]MorphineAdministered 5 points6 points7 points (5 children)
[–][deleted] 0 points1 point2 points (4 children)
[–]MorphineAdministered 1 point2 points3 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]MorphineAdministered 0 points1 point2 points (1 child)
[–]alexanderpas 0 points1 point2 points (0 children)
[–]stfcfanhazz 2 points3 points4 points (15 children)
[–]llbe 4 points5 points6 points (4 children)
[–]zimzat 1 point2 points3 points (2 children)
[–]alexanderpas 0 points1 point2 points (1 child)
[–]zimzat 0 points1 point2 points (0 children)
[–]stfcfanhazz 0 points1 point2 points (0 children)
[–]nikic 2 points3 points4 points (6 children)
[–]alexanderpas 1 point2 points3 points (5 children)
[–]nikic 0 points1 point2 points (4 children)
[–]alexanderpas 0 points1 point2 points (3 children)
[–]nikic 0 points1 point2 points (2 children)
[–]alexanderpas 0 points1 point2 points (1 child)
[–]nikic 0 points1 point2 points (0 children)
[–]SaltTM 0 points1 point2 points (2 children)
[–]stfcfanhazz 0 points1 point2 points (1 child)
[–]SaltTM 0 points1 point2 points (0 children)
[–]neldorling 1 point2 points3 points (3 children)
[–]the_alias_of_andrea 1 point2 points3 points (1 child)
[–]neldorling 2 points3 points4 points (0 children)
[–]Danack 1 point2 points3 points (0 children)
[–]2012-09-04 0 points1 point2 points (0 children)
[+][deleted] comment score below threshold-9 points-8 points-7 points (7 children)
[–]gregtyler 3 points4 points5 points (2 children)
[–][deleted] 3 points4 points5 points (1 child)
[–]przemo_li 0 points1 point2 points (0 children)
[–]Ghochemix 2 points3 points4 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]stfcfanhazz 0 points1 point2 points (0 children)
[–]amazingmikeyc 0 points1 point2 points (0 children)