URL building PSR

371 views
Skip to first unread message

Dracony

unread,
Dec 30, 2016, 12:05:21 PM12/30/16
to PHP Framework Interoperability Group
So I read through the Routing PSR idea and honestly I can't think of it having too many use cases. Why would you ever need to replace a whole router really? But that got me thinking about a different, and much more useful usecase.

While matching the URL to some parameters is usually done once and by the framework itself usually what happens a lot is URL generation within the app. So instead of a full blown routing PSR I propose a simpler one which just provides interfaces for generating URLs from an array of parameters. This would be much more useful immediately since these URL generators could be passed to template renderers to build links, which would make integration of these engines within frameworks easier. This would also mean that some payment processing libraries would be easier to use since they would be able to automatically generate URLs to appropriate controllers etc.

Larry Garfield

unread,
Dec 30, 2016, 2:38:50 PM12/30/16
to php...@googlegroups.com
PSR-7 already defines an evolvable Uri object:

http://www.php-fig.org/psr/psr-7/#3-5-psr-http-message-uriinterface

That seems sufficient for most use cases.

--Larry Garfield

Roman Tsiupa

unread,
Dec 30, 2016, 2:42:16 PM12/30/16
to PHP FIG
Thats not what I had in mind. 
I was thinking about something like this:


Not evolving the url, but generating a URL from a route name and and array of parameters. 

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/q2T5hJQQhwk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+unsubscribe@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/7a248957-75ef-b44d-5434-e87e73607d8f%40garfieldtech.com.
For more options, visit https://groups.google.com/d/optout.

Hannah Warmbier

unread,
Jan 1, 2017, 1:59:18 PM1/1/17
to PHP Framework Interoperability Group
Not sure if this is what you're looking for either, but are you aware of RFC 6570?


There are a number of PHP libraries that implement it.

On Friday, December 30, 2016 at 1:42:16 PM UTC-6, Dracony wrote:
Thats not what I had in mind. 
I was thinking about something like this:


Not evolving the url, but generating a URL from a route name and and array of parameters. 
On 30 Dec 2016 20:38, "Larry Garfield" <la...@garfieldtech.com> wrote:
On 12/30/2016 11:05 AM, Dracony wrote:
So I read through the Routing PSR idea and honestly I can't think of it having too many use cases. Why would you ever need to replace a whole router really? But that got me thinking about a different, and much more useful usecase.

While matching the URL to some parameters is usually done once and by the framework itself usually what happens a lot is URL generation within the app. So instead of a full blown routing PSR I propose a simpler one which just provides interfaces for generating URLs from an array of parameters. This would be much more useful immediately since these URL generators could be passed to template renderers to build links, which would make integration of these engines within frameworks easier. This would also mean that some payment processing libraries would be easier to use since they would be able to automatically generate URLs to appropriate controllers etc.

PSR-7 already defines an evolvable Uri object:

http://www.php-fig.org/psr/psr-7/#3-5-psr-http-message-uriinterface

That seems sufficient for most use cases.

--Larry Garfield

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/q2T5hJQQhwk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

Roman Tsiupa

unread,
Jan 1, 2017, 2:36:05 PM1/1/17
to PHP FIG
Still not what I had in mind. A templating engine that is generating links on your page should really have no idea of the actual URL structure, just a route name.

E.g. when you do in twig: 



 <a href="{{ path('article_show', {'slug': article.slug}) }}">
        {{ article.title }}
 </a>

To unsubscribe from this group and all its topics, send an email to php-fig+unsubscribe@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Woody Gilk

unread,
Jan 1, 2017, 7:12:13 PM1/1/17
to PHP Framework Interoperability Group
Hannah,

Thanks for sharing that, it looks super useful for a number of situations!


Roman,

All you would need to use RFC 6570 is a function/method that returns a route "template" from a name:


function routeUrl($name, array $params)
{
    $template = function_to_get_route_template($name);
    return rfc6570_expand($template, $params);
}





--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+unsubscribe@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Roman Tsiupa

unread,
Jan 1, 2017, 9:17:32 PM1/1/17
to PHP FIG
Well you still need to call such a function something, right? Also not all route parameters necessarily map directly 1:1 to url parameters. So I think a more general solution is better.

Also simply returning a url template would require client libraries to also do the substitutions instead of just getting a ready made url.

Hannah Warmbier

unread,
Jan 2, 2017, 6:39:48 PM1/2/17
to PHP Framework Interoperability Group
If by 'route parameters' you mean params that are injected into or used by a controller, this is not simple URL building and, IMO, should not be the concern of a router.

I'm not sure how FIG could standardize this. Routing? Sure. URL building (e.g. RFC 6570 to PSR-7 Uri)? Sure. But I think you're venturing into a part of libraries/frameworks that is specific/unique to each, and doesn't make sense to standardize.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/q2T5hJQQhwk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Dracony

unread,
Jan 3, 2017, 7:01:31 AM1/3/17
to PHP Framework Interoperability Group
Well,think of that templating example. To make the Twig `path` function work the template engine needs to be integrated with the router. Having an interface for that would make template engines easier to integrate.

Chuck Reeves

unread,
Jan 4, 2017, 9:58:57 AM1/4/17
to PHP Framework Interoperability Group
Dracony,  

Cant the twig 'path' function just be refactored to take in PSR-7 UrlInterface as well?

Roman Tsiupa

unread,
Jan 4, 2017, 10:08:48 AM1/4/17
to PHP FIG
No, because you don't use the URL in twig, you use a symfony route, it is not a URL.

To unsubscribe from this group and all its topics, send an email to php-fig+unsubscribe@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Geert Eltink

unread,
Jan 5, 2017, 1:51:09 AM1/5/17
to PHP Framework Interoperability Group
So I read through the Routing PSR idea and honestly I can't think of it having too many use cases. Why would you ever need to replace a whole router really?
 
It's the same for the container interface (PSR-11). You can't replace a container by just changing the package in composer.json because of differences in configuration, it's still very useful to have that standard.

If I understand correctly you want to create something to be able to generate url's in different places. With zend-expressive the UrlHelper class takes care of this. Well, sort of. It's a helper but doesn't generate the url's itself. It takes the route name and parameters, reuses the current active route if required and passes all data to the router, which generates the route.

The router does the real URL generation. That's also the reason the UrlHelper is just a helper. The router knows how to generate routes and if I understand you correctly, you want to take that part out of the routers.

I think FastRoute is the only exception here since it only does routing and doesn't generate URL's. So for zend-expressive we created our own route generator for it: https://github.com/zendframework/zend-expressive-fastroute/blob/e99e03eb334981859a975e7fd4224cdff29144bf/src/FastRouteRouter.php#L263

To make the Twig `path` function work the template engine needs to be integrated with the router. Having an interface for that would make template engines easier to integrate.

In Expressive the UrlHelper is injected in a custom Twig Extension: https://github.com/zendframework/zend-expressive-twigrenderer/blob/master/src/TwigExtension.php
Since parameters and defined routes (which are known to the router) are involved, it's pretty much useless to let this helper generate the routes. It's already handled by most routers already.

In my opinion it would be more useful to create a router PSR than creating a PSR for something that is handled already by most routers. The UrlHelper is useful in zend-expressive, other frameworks do it differently and might have no use for it.


Kind regards,

Geert Eltink.

Oscar Otero

unread,
Jan 6, 2017, 5:41:17 AM1/6/17
to php...@googlegroups.com
I like the idea of a PSR to generate urls, it’s useful and I can imagine several use cases. Let’s say the interface can be something like the following:

public function generateUri(string $name, array $attributes);

1. This can be used by the controller:

function (ServerRequestInterface $request) : ResponseInterface
{
    $uri = $uriFactory->generateUri(‘post’, [‘id’ => 34]);

    return new RedirectResponse($uri);
}

2. It can be used by the template engine:

<a href=“<?= $this->generateUri(‘post’, [‘id’ => 34]) ?>”>
    Go to post
</a>

3. Or if the template engine is not PHP native:

<a href=“{{ generateUri(‘post’, {id: 34}) }}”>
    Go to post
</a>

4. Even, we can configure the models to generate its own urls:

$postModel->setUriFactory($uriFactory, [’route’ => ‘post’, ‘attribute’ => ‘id’]);

$posts = $postModel->selectAll();

foreach ($posts as $post) {
    echo $post->getUri();
}

5. And if we allow the name argument to be anything, we can create a RFC 6570 generator:

$uri = $uriFactory->generateUri(‘http://example.com/posts/{id}, [‘id’ => 34]);

6. Let’s say we had changed the ugly urls of our site to new seo friendly. For example, “/posts?id=234” to “/posts/beauty-slug”, we can use this geneator to map the urls and even create a middleware for that:

function (ServerRequestInterface $request, DelegateInterface $next) : ResponseInterface
{
    $oldUri = (string) $request->getUri();
    $newUri = $this->uriMapper->generateUri($oldUri);
    if ($newUri) {
        return (new Response())->withStatus(301)->withHeader(‘Location: ‘.$newUri);
    }

    return $next->process($request);
}

I can imagine more examples, but these are enough to illustrate the usefulness of this.




Reply all
Reply to author
Forward
0 new messages