8000 [Routing] Fix support for stringable parameters by OskarStark · Pull Request #42057 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Routing] Fix support for stringable parameters #42057

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

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
[Routing] Fix http_build_query does not cast
  • Loading branch information
OskarStark committed Jul 13, 2021
commit 2a235d7f1822a9ff98fff35697e422cd5be64c71
9 changes: 9 additions & 0 deletions src/Symfony/Component/Routing/Generator/UrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
return $a == $b ? 0 : 1;
});

array_walk_recursive($extra, $caster = static function (&$v) use (&$caster) {
if ($v instanceof \stdClass) {
$v = (array) $v;
Copy link
Contributor
@Tobion Tobion Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is breaking for classes that extend stdClass, https://3v4l.org/6e5Vj

array_walk_recursive($v, $caster);
} elseif (null !== $v) {
$v = (string) $v;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about array-like objects here? I'd guess that Iterators/ArrayAccess implementations would want to behave similar to (array) $v in the above case. What should happen in the case of an Iterator or ArrayAccess (for example) where the object can be converted to a string representation?

Would it be an idea to give users control over how the parameters should be rendered, perhaps through an interface or custom parameter object that can deal with this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For those, we should mimik what http_build_query does, nothing more. A test case would help know.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the object does not implement __toString this would throw an exception which is a bc break.
and even if it did, there would be a bc break because http_build_query uses the public properties normally.
see https://3v4l.org/9cDG3

Copy link
Contributor Author
@OskarStark OskarStark Jul 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the object does not implement __toString this would throw an exception which is a bc break.

I added a test case and check for __toString() in 31d6937

and even if it did, there would be a bc break because http_build_query uses the public properties normally.
see https://3v4l.org/9cDG3

We could check if some public properties exists and do nothing instead of using toString()

}
});

// extract fragment
$fragment = $defaults['_fragment'] ?? '';

Expand Down
48 changes: 48 additions & 0 deletions src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,46 @@ public function testUrlWithNullExtraParameters()
$this->assertEquals('http://localhost/app.php/testing', $url);
}

public function testRelativeUrlWithStringableObjectParameter()
{
$stringableObject = new StringableObject();

$routes = $this->getRoutes('test', new Route('/testing/{foo}'));
$url = $this->getGenerator($routes)->generate('test', ['foo' => $stringableObject], UrlGeneratorInterface::ABSOLUTE_PATH);

$this->assertSame('/app.php/testing/bar', $url);
}

public function testRelativeUrlWithStringableObjectExtraParameter()
{
$stringableObject = new StringableObject();

$routes = $this->getRoutes('test', new Route('/testing'));
$url = $this->getGenerator($routes)->generate('test', ['stringable' => $stringableObject], UrlGeneratorInterface::ABSOLUTE_PATH);

$this->assertSame('/app.php/testing?stringable=bar', $url);
}

public function testAbsoluteUrlWithStringableObjectExtraParameter()
{
$stringableObject = new StringableObject();

$routes = $this->getRoutes('test', new Route('/testing'));
$url = $this->getGenerator($routes)->generate('test', ['stringable' => $stringableObject], UrlGeneratorInterface::ABSOLUTE_URL);

$this->assertSame('http://localhost/app.php/testing?stringable=bar', $url);
}

public function testAbsoluteUrlWithStringableObjectExtraParameterInArray()
{
$stringableObject = new StringableObject();

$routes = $this->getRoutes('test', new Route('/testing'));
$url = $this->getGenerator($routes)->generate('test', ['key' => ['stringable' => $stringableObject]], UrlGeneratorInterface::ABSOLUTE_URL);

$this->assertSame('http://localhost/app.php/testing?key%5Bstringable%5D=bar', $url);
}

public function testUrlWithExtraParametersFromGlobals()
{
$routes = $this->getRoutes('test', new Route('/testing'));
Expand Down Expand Up @@ -892,3 +932,11 @@ protected function getRoutes($name, Route $route)
return $routes;
}
}

class StringableObject
{
public function __toString()
{
return 'bar';
}
}
0