Skip to content

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

Open
@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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions