Skip to content

calling Uri::__toString() leads to unexpected object comparison result #622

@pawelbaranski

Description

@pawelbaranski

Description
calling a __toString() getter, changes the Uri object state, which makes == comparison for Uri object unreliable. That is essentially a BC break in my opinion.

How to reproduce

use GuzzleHttp\Psr7\Uri;

$uri1 = new Uri('http://test.com');
$uri2 = new Uri('http://test.com');

var_dump($uri1 == $uri2); //true

$uri2->__toString();

var_dump($uri1 == $uri2); //false

Possible Solution

it is caused by composedComponents that is used to store the value of resolved uri, and it is done lazy, on first call.

public function __toString(): string
{
    if ($this->composedComponents === null) {
        $this->composedComponents = self::composeComponents(
            $this->scheme,
            $this->getAuthority(),
            $this->path,
            $this->query,
            $this->fragment
        );
    }

    return $this->composedComponents;
}

I see two solutions:

  • either do not store that value, somewhat on behalf of the client, and make the client store it if he needs to have it resolved
  • or resolve it in __constructor

Additional Context

I am in the middle of migration to newer php version, and I needed to update guzzlehttp/psr7 package and ended up fixing the codebase as we have == comparison used on Uri objects, thankfully there were tests that also broke so was not a surprise on production.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions