[PSR-17] UriInterface|string $uri - what about __toString() ?

414 views
Skip to first unread message

Tomasz Darmetko

unread,
Jul 9, 2018, 10:23:42 AM7/9/18
to PHP Framework Interoperability Group
Hello,

In many places in PSR-17 we accept `UriInterface|string $uri`  - what should be the semantics of accepting `string`?

Should objects implementing `__toString()` be accepted, rejected, or should it be left to an implementation?

Just as a reminder:
- without declare(strict_types=1); `__toString()` is accepted as string: https://3v4l.org/HifEk
- with declare(strict_types=1); `__toString()` is not accepted as string: https://3v4l.org/OARtu

Guzzle, for example, choose to reject objects implementing `__toString()`: https://github.com/guzzle/psr7/blob/master/src/functions.php#L54

Best regards,
Tomasz Darmetko

Woody Gilk

unread,
Jul 9, 2018, 10:32:53 AM7/9/18
to PHP Framework Interoperability Group
I think it should be strictly `UriInterface|string`.
--
Woody Gilk
https://shadowhand.me
> --
> You received this message because you are subscribed to the Google Groups
> "PHP Framework Interoperability Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to php-fig+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/9c5cd846-862d-4b5a-bd45-2da19883bfc4%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

ignace nyamagana

unread,
Jul 17, 2018, 10:31:47 AM7/17/18
to PHP Framework Interoperability Group
IHMO, with PHP 7.2 supporting parameter type widening I believe it's up to the implementation to support __toString or not. But if you want your code to be as much portable as it can get you should write it using only UriInterface and/or string. But nothing prevents your own implementation to support other types.

It's up to you

Tomasz Darmetko

unread,
Jul 17, 2018, 11:51:44 AM7/17/18
to PHP Framework Interoperability Group
I'm more concerned about the end users of the interface.

If my application already implements URL value object with __toString, should I be able to pass it directly?

If one implementation will accept it and other not, I won't be able to swap them. Or I will get nasty surprises after I do.

I personally think we should accept all object implementing __toString as strings. After all, it improves interoperability.

Either way IMO it should be clarified to avoid issues.

ignace nyamagana

unread,
Jul 17, 2018, 12:17:45 PM7/17/18
to PHP Framework Interoperability Group
If your concern is the end user then stick to UriInterface|string because you want your code to be interoperable I believe. But again nothing prevents you to broaden the acceptance argument ... again thanks to parameter widening. It's up to your to decide. FWIW Slim accepts object with __toString with its UriInterface implementation.

Matthew Weier O'Phinney

unread,
Jul 17, 2018, 12:49:22 PM7/17/18
to php...@googlegroups.com
On Tue, Jul 17, 2018 at 10:51 AM Tomasz Darmetko <isi...@gmail.com> wrote:
>
> I'm more concerned about the end users of the interface.
>
> If my application already implements URL value object with __toString, should I be able to pass it directly?
>
> If one implementation will accept it and other not, I won't be able to swap them. Or I will get nasty surprises after I do.
>
> I personally think we should accept all object implementing __toString as strings. After all, it improves interoperability.
>
> Either way IMO it should be clarified to avoid issues.

Accepting `string`, and knowing that `UriInterface` defines
`__toString()` explicitly, if you're worried about interop, all you
need to do is cast the argument to a string when passing it to the
factory:

$request = $factory->createRequest('GET', (string) $uri);

While this would mean creating a new `Uri` instance if you passed one,
it satisfies the interoperability concerns. Anything else is
duck-typing, and requires reflection to manage.
> To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/4e452879-2dbe-4bb4-8218-4d0f0729943f%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Matthew Weier O'Phinney
mweiero...@gmail.com
https://mwop.net/

Tomasz Darmetko

unread,
Jul 17, 2018, 12:58:41 PM7/17/18
to PHP Framework Interoperability Group
Just to clarify - I'm not implementing this interface. I'm following FIG out of pure interest. There is a lot to learn about software engineering just by observing smart people at work ;).

I was using Guzzle and was surprised that my object with __toString was rejected.

I'm not using strict types and the perfectly valid interpretation of "string" is "string or objects implementing __toString() that will be converted to string in an expected way".

Therefore $request = $factory->createRequest('GET', (string) $uri); should not be required. (I solved it already, so it's not an issue per se for me anymore)

The fact that other end users may not be able to swap one major implementation (Slim) to another (Guzzle) should be a concern IMO and warrant a clarification in the interface or at least a warning.
Reply all
Reply to author
Forward
0 new messages