Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP does not recognize Stringy as string #167

Open
apapsch opened this issue Oct 5, 2017 · 3 comments
Open

PHP does not recognize Stringy as string #167

apapsch opened this issue Oct 5, 2017 · 3 comments

Comments

@apapsch
Copy link

apapsch commented Oct 5, 2017

Please take a look at this constructor from https://github.com/lanthaler/IRI/blob/a04d4f923700dc5b4a19e1e105f978b50647efaa/IRI.php#L80

public function __construct($iri = null)
{
    if (null === $iri) {
        return;
    } elseif (is_string($iri)) {
        $this->parse($iri);
    } elseif ($iri instanceof IRI) {
        $this->scheme = $iri->scheme;
        $this->userinfo = $iri->userinfo;
        $this->host = $iri->host;
        $this->port = $iri->port;
        $this->path = $iri->path;
        $this->query = $iri->query;
        $this->fragment = $iri->fragment;
    } else {
        throw new \InvalidArgumentException(
            'Expecting a string or an IRI, got ' .
            (is_object($iri) ? get_class($iri) : gettype($iri))
        );
    }
}

I naively wrote this:

$foo = new Stringy('bar');
$baz = new IRI($foo);

and got that:

 InvalidArgumentException: Expecting a string or an IRI, got Stringy\Stringy

The solution is explicit type conversion:

$baz = new IRI((string)$foo);

My naive approach was done under the impression that Stringy should act like a PHP string, even though it is an object. How would you approach this issue? I can imagine:

  1. Do explicit type conversion everywhere. But then you litter your code and possibly copy strings when you could pass them by reference.
  2. Limit Stringy usage. But then you don't have the nice API and don't get strings passed by reference most of the time.
  3. Do some magic in PHP core in order for code to treat string classes as strings without needing changes (i.e. no littering with (string)). That could include an interface which is_string recognizes and returns true for. Also, an instance of the class implementing the interface would be treated as a PHP string most of the time, except when methods are invoked on the instance. And the string object would be passed by reference of course.

Approaches 1 and 2 seem like hacks, though they are in reach. Approach 3 is the best from user perspective but I don't know if it's viable. It might entail a ton of changes in PHP core.

@ArchitectNate
Copy link

ArchitectNate commented Oct 6, 2017

Peter Barney has a decent solution, replace your is_string() calls with is_stringy() calls
http://php.net/manual/en/function.is-string.php#121637

<?php
// determine if the passed argument can be treated like a string.

function is_stringy($text) {

    return (is_string($text) || (is_object($text) && method_exists($text, '__toString' ));
}

This won't solve TypeHinting, especially with strict typing.

@apapsch
Copy link
Author

apapsch commented Oct 9, 2017

That's doable, although not feasable for third party code. It might be worth pursuing this extension of is_string in PHP core, WDYT?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants