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

Rewrite Router->urlFor() to generate complete Urls #2493

Merged
merged 22 commits into from
Apr 23, 2019

Conversation

Jmp00000001
Copy link

Hello!

Like @splitbrain mentioned in slimphp/Twig-View#101 there is actually no way to generate a complete url while slim runs in a sub directory.

This pull request refactors slimphp/Twig-View#102 TwigExtension->urlFor() to Router->urlFor()

Is there any chance you can merge this?
Let me know if this pull request need improvement.

@coveralls
Copy link

coveralls commented Aug 22, 2018

Coverage Status

Coverage increased (+0.006%) to 97.838% when pulling e6ff493 on Jmp00000001:3.x into f0718f6 on slimphp:3.x.

Slim/Router.php Outdated
return $this->pathFor($name, $data, $queryParams);
// Check if container['request'] is initialized.
if (!$this->container->has('request')) {
throw new RuntimeException('Request object is not initialized yet.');

Choose a reason for hiding this comment

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

For one of the use cases (creating email templates) it might very well happen that this mechanism is called without a request context when emails are generated from a command line script or from a task queue.

There is no way to automatically build the base URL without a Request object. So instead of just throwing an Exception here, it would probably be helpful to be able to configure the base URL from a config setting and fall back to it if no Request is available.

Copy link
Member

Choose a reason for hiding this comment

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

Let's treat this as a separate issue for a subsequent PR.

Copy link
Author

Choose a reason for hiding this comment

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

These should be obsolete now, since the $uri gets passed as argument and $request ist not needed anymore

@akrabat
Copy link
Member

akrabat commented Sep 16, 2018

There's a potential problem here in that this is not backwards compatible.

@vlakoff
Copy link
Contributor

vlakoff commented Sep 25, 2018

Refs #1316.

Actually, the name urlFor was not that wrong, as an URL can be relative (i.e. the scheme and autority are optional). Meanwhile, the "path" is a very specific part of the URL, which doesn't include the query string and the anchor.

I'd suggest:

  • adding a method fullUrlFor (easy to remember I think),
  • and replacing again pathFor with urlFor (mainly because "url" is by far the most used name in other PHP frameworks). In Slim 3, allow both pathFor and urlFor (removing the deprecation notice, to ease migration), and in Slim 4, deprecate pathFor.

As a result, in Slim 4 we would have urlFor and fullUrlFor, and we could use fullUrlFor already in Slim 3.

@akrabat
Copy link
Member

akrabat commented Apr 6, 2019

I'd suggest:

  • adding a method fullUrlFor (easy to remember I think),
  • and replacing again pathFor with urlFor (mainly because "url" is by far the most used name in other PHP frameworks). In Slim 3, allow both pathFor and urlFor (removing the deprecation notice, to ease migration), and in Slim 4, deprecate pathFor.

As a result, in Slim 4 we would have urlFor and fullUrlFor, and we could use fullUrlFor already in Slim 3.

I agree. Let's call this fullUrlFor and make sure we also create a PR for Slim 4 too.

@akrabat akrabat added the Slim 4 label Apr 6, 2019
@l0gicgate
Copy link
Member

@akrabat I can add this PR as part of the router refactoring process going on at the moment for the Slim 4 branch. It’ll probably be last though.

@akrabat
Copy link
Member

akrabat commented Apr 8, 2019

@akrabat I can add this PR as part of the router refactoring process going on at the moment for the Slim 4 branch. It’ll probably be last though.

Okay. Separate PR :)

@akrabat
Copy link
Member

akrabat commented Apr 8, 2019

Next step for this one is for @Jmp00000001 to update this PR.

@Jmp00000001
Copy link
Author

Hello,

I will have a look after work.

This should be updated?

I'd suggest:

adding a method fullUrlFor (easy to remember I think),
and replacing again pathFor with urlFor (mainly because "url" is by far the most used name in other PHP frameworks). In Slim 3, allow both pathFor and urlFor (removing the deprecation notice, to ease migration), and in Slim 4, deprecate pathFor.
As a result, in Slim 4 we would have urlFor and fullUrlFor, and we could use fullUrlFor already in Slim 3.

@Jmp00000001
Copy link
Author

I have

  • refactored my implementation of Router::urlFor() to Router:fullUrlFor()
  • restored the old Router::urlFor()
  • removed the deprication warning in Router::urlFor()

Let me know if I missed something :)

@vlakoff
Copy link
Contributor

vlakoff commented Apr 8, 2019

Just a nitpick: we could also reverse the Slim 3 BC alias, i.e. make pathFor() call urlFor(), as the latter should be the preferred/canonical one.

@Jmp00000001
Copy link
Author

Here you go :)

@akrabat
Copy link
Member

akrabat commented Apr 9, 2019

Here you go :)

Please remove the This method is deprecated. Use pathFor() from now on. docblock comment.

@l0gicgate l0gicgate mentioned this pull request Apr 17, 2019
7 tasks
Slim/Router.php Outdated

/** @var Uri $uri */
$uri = $this->container->get('request')->getUri();
if (is_string($uri)) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a test case for this condition as well please?

Copy link
Author

Choose a reason for hiding this comment

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

I think the check that $uri is a string is not required at all.
There is no way Request::getUri() returns something different than a UriInterface object:

  • Only the Request constructor sets the $uri and expects an UriInterface. The constructor will throw otherwise (at latest when calling class methods like Uri::getPort())
  • The docblock of Request::getUri() also mentions: This method MUST return a UriInterface instance

No clue what I was thinking..
I simply remove that check.

Copy link
Member

Choose a reason for hiding this comment

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

So this brings me to question the method signature in the first place. Look at the way I implemented it in Slim 4:
https://github.com/slimphp/Slim/blob/4.x/Slim/Routing/RouteParser.php#L129-L136

Since this is a new method, we should force a UriInterface being passed in by the user instead of trying to do gymnastics to get to it.

Copy link
Member

@l0gicgate l0gicgate left a comment

Choose a reason for hiding this comment

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

Please add test coverage for the to aforementioned conditions and I'll merge. Thanks!

@Jmp00000001
Copy link
Author

I will have a look today/tomorrow.
Just got back from vacation :)

@l0gicgate l0gicgate merged commit 89c0149 into slimphp:3.x Apr 23, 2019
@l0gicgate l0gicgate added this to the 3.12.2 milestone Apr 23, 2019
@vlakoff
Copy link
Contributor

vlakoff commented Apr 23, 2019

I'd suggest renaming relativePathFor to relativeUrlFor as well.


I'd also like to reference this SO answer: Absolute vs relative URLs.

And here are the correspondences:

Slim SO answer
fullUrlFor() 1. Absolute URL
urlFor() 4. Root-relative URL
relativeUrlFor() 2. Relative URL

@l0gicgate
Copy link
Member

@vlakoff we cannot change relativePathFor in the 3.x branch as it would be a BC change.

However, I'm open to that for Slim 4 since we're not even in alpha yet.

@vlakoff
Copy link
Contributor

vlakoff commented Apr 24, 2019

Same as the urlFor() change, keeping the old name as a BC alias in Slim 3.

@l0gicgate
Copy link
Member

l0gicgate commented Apr 24, 2019

@vlakoff I'm going to PR that for Slim 4 on the RouteParser. I think using the same terminology everywhere makes sense. We'll deprecate relativePathFor() and pathFor() and use as you described:

  • RouteParser::fullUrlFor() - Absolute URL
  • RouteParser::urlFor() - Root Relative URl
  • RouteParser::relativeUrlFor() - Relative URL

I also want to point out that there's not going to be any deprecation warning. Since Router was split into RouteCollector and RouteParser those are entirely new interfaces and there's no point in including deprecated methods/warnings since the user will have to re-learn the new interfaces anyway.

As for Slim 3, I don't think any further changes are warranted since we're so deep in the release cycle. The functionality is there and is usable, that's what matters most.

@Jmp00000001
Copy link
Author

Thanks for merging!

@vlakoff
Copy link
Contributor

vlakoff commented Apr 24, 2019

Considering that urlFor() and relativeUrlFor() don't produce URLs strictly speaking, as they don't contain the protocol and server, but only the path + optional query string, I'd like to make sure everyone is comfortable with these new names.

I chose these names trying to apply the best possible the principle of least astonishment. But on second thought, an other acceptable naming scheme could be "relativePathFor() / pathFor() / urlFor()".

This is really worrying me and it's still time to change if necessary, please provide your feedback on this matter!

@l0gicgate
Copy link
Member

Wouldn’t the term “Uri” instead of path apply here then @vlakoff?

  • Uri - Uniform Resource Identifier
  • Url - Uniform Resource Locator

A URL should be with protocol. A URI should be part of a url much like a path is. So relativeUriFor(), uriFor() and fullUrlFor() would make sense.

@vlakoff
Copy link
Contributor

vlakoff commented Apr 25, 2019

That's quite a headache!

I have done some reading, and it (probably arguably) seems that what we are dealing with are really URLs, as they are resources' locations; for the value to be useful, the scheme and domain have to be known, i.e. specified but could also be deduced. In our case, the browser does the latter, by completing the provided URL using the current location.

Further reading: What is the difference between a URI, a URL and a URN?

Also worth noting:

But doesn't the W3C now say that URLs and URIs are the same thing?
Yes. The W3C realized that there is a ton of confusion about this. They issued a URI clarification document that says that it is now OK to use the terms URL and URI interchangeably (to mean URI). It is no longer useful to strictly segment URIs into different types such as URL, URN, and URC.

Finally, using "uri" surely would be very confusing for the users!

@l0gicgate
Copy link
Member

it is now OK to use the terms URL and URI interchangeably (to mean URI). It is no longer useful to strictly segment URIs into different types such as URL, URN, and URC.

By that logic it's totally fine to use url as a prefix/suffix for these method even when referring to a path. I think the key here is in the documentation.

@vlakoff
Copy link
Contributor

vlakoff commented Apr 25, 2019

Agree with the above.

So, personally I'd bend staying on urlFor()/fullUrlFor()/relativeUrlFor().
(BTW, relativeUrlFor() should only be used for very specific cases)

To summarize:

  • urlFor(): the regular one, e.g. for the href attributes
  • fullUrlFor(): when you need… the full url, with scheme and domain
  • relativeUrlFor(): plz use this one as little as possible, relative paths cause so much troubles!

So, shall we settle on this?

@l0gicgate
Copy link
Member

@vlakoff

We are going to leave the terminology as in in Slim 3.

But for Slim 4 the RouteParserInterface is as you described:

  • RouteParser::fullUrlFor()
  • RouteParser::urlFor()
  • RouteParser::relativeUrlFor()

So I think this is settled! Thanks for your input.

@vlakoff
Copy link
Contributor

vlakoff commented Apr 25, 2019

I apologize for the extended chat… I really wanted to be sure the new naming convention was good. I would have felt so bad if I had introduced a bad naming scheme in Slim 4!

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

Successfully merging this pull request may close these issues.

None yet

6 participants