Skip to content

Commit e40c725

Browse files
committed
Complement UriTemplate expand with a method to return PSR7 Uri objects
1 parent b2642fb commit e40c725

File tree

3 files changed

+78
-18
lines changed

3 files changed

+78
-18
lines changed

docs/uri/7.0/uri-template.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,18 @@ $template = 'https://example.com/hotels/{hotel}/bookings/{booking}';
2323
$params = ['booking' => '42', 'hotel' => 'Rest & Relax'];
2424

2525
$uriTemplate = new UriTemplate($template);
26-
$uri = $uriTemplate->expand($params); // instance of League\Uri\Uri
27-
$rfc3986Uri = $uriTemplate->expandToUri($params); // instance of Uri\Rfc3986\Uri
28-
$whatWgUrl = $uriTemplate->expandToUrl($params); // instance of Uri\Whatwg\Url
26+
$uri = $uriTemplate->expand($params); // instance of League\Uri\Uri
27+
$rfc3986Uri = $uriTemplate->expandToUri($params); // instance of Uri\Rfc3986\Uri
28+
$whatWgUrl = $uriTemplate->expandToUrl($params); // instance of Uri\Whatwg\Url
29+
$psr7Uri = $uriTemplate->expandToPsr7Uri($params); // instance of Psr7 UriInterface
2930

3031
echo $uri; //display https://example.com/hotels/Rest%20%26%20Relax/bookings/42"
3132
~~~
3233

33-
<p class="message-notice"><code>expandToUri()</code> and <code>expandToUrl()</code> are available since
34+
<p class="message-notice"><code>expandToUri()</code>, <code>expandToUrl()</code> and <code>expandToPsr7Uri()</code> are available since
3435
version <code>7.6.0</code></p>
3536

36-
<p class="message-info">Since version <code>7.6</code> the method takes a second optional parameter
37+
<p class="message-info">Since version <code>7.6</code> the <code>expand()</code> method takes a second optional parameter
3738
which serves as a base URI. The generated URI is resolved against the Base URI.</p>
3839

3940
~~~php
@@ -48,6 +49,7 @@ $uriTemplate = new UriTemplate($template);
4849
$uri = $uriTemplate->expand($params, 'https://example.com'); // instance of League\Uri\Uri
4950
$rfc3986Uri = $uriTemplate->expandToUri($params, 'https://example.com'); // instance of Uri\Rfc3986\Uri
5051
$whatWgUrl = $uriTemplate->expandToUrl($params, 'https://example.com'); // instance of Uri\Whatwg\Url
52+
$whatWgUrl = $uriTemplate->expandToPsr7Uri($params, 'https://example.com'); // instance of League\Uri\Http
5153

5254
echo $uri; //display https://example.com/hotels/Rest%20%26%20Relax/bookings/42"
5355
~~~
@@ -97,8 +99,8 @@ echo $uriTemplate->expand($params), PHP_EOL;
9799
//displays https://api.twitter.com/2.0/search/j/john/?q=a&q=b&limit=10
98100
~~~
99101

100-
The `expandToUri()` and the `expandToUrl()` methods will act exactly like the `expand()` method
101-
but will instead return a `Uri\Rfc3986\Uri` and a `Uri\Whatwg\Url` object respectively.
102+
The `expandToUri()`, `expandToUrl()` and `expandToPsr7Uri()` methods will act exactly like the `expand()` method
103+
but will instead return a `Uri\Rfc3986\Uri`, a `Uri\Whatwg\Url` or a `Psr7\Http\Message\UriInterface` object respectively.
102104

103105
<p class="message-warning">a WHATWG URL must always be absolute if the URI template is not you
104106
MUST provide a base URL to <code>expandToUrl()</code> otherwise an <code>Uri\WhatWg\InvalidUrlException</code>
@@ -121,6 +123,31 @@ echo $uriTemplate->expandToUrl($params, 'https://api.twitter.com')->toAsciiStrin
121123
echo $uriTemplate->expandToUrl($params); //will throw
122124
~~~
123125

126+
<p class="message-info">You may return a different <code>Psr7\Http\Message\UriInterface</code> object if you
127+
provide to the <code>expandToPsr7Uri</code> your own <code>Psr\Http\Message\UriFactoryInterface</code> class
128+
as the third optional argument.</p>
129+
130+
~~~php
131+
use League\Uri\UriTemplate;
132+
use Laminas\Diactoros\UriFactory;
133+
134+
$template = '/{version}/search/{term:1}/{term}/{?q*,limit}';
135+
//the template represents a non-absolute URL
136+
137+
$params = [
138+
'term' => 'john',
139+
'q' => ['a', 'b'],
140+
'limit' => '10',
141+
'version' => '2.0'
142+
];
143+
144+
$uriTemplate = new UriTemplate($template, ['version' => '1.1']);
145+
$uri = $uriTemplate->expandToPsr7Uri($params, 'https://api.twitter.com', new UriFactory());
146+
$uri::class; // returns 'Laminas\Diactoros\Uri'
147+
~~~
148+
149+
By default, if no factory is provided, the returned PSR-7 `UriInterface` object is a `League\Uri\Http` instance.
150+
124151
### Updating the default variables
125152

126153
At any given time you may update your default variables but since the `UriTemplate`

uri/CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ All Notable changes to `League\Uri` will be documented in this file
3333
- `Uri::withUsername` returns a new `Uri` instance with the updated username component.
3434
- `Uri::withPassword` returns a new `Uri` instance with the updated password component.
3535
- `UriTemplate` implements the `Stringable` interface
36-
- `UriTemplate::expandToUri` and `UriTemplate::expandToUrl`
37-
- `UriTemplate::expandToUriOrFail` and `UriTemplate::expandToUrlOrFail`
38-
- `UriTemplate::expand` takes a second optional parameter which represents a base URI to resolve the URI from.
36+
- `UriTemplate::expandToUri` and `UriTemplate::expandToUriOrFail`
37+
- `UriTemplate::expandToUrl` and `UriTemplate::expandToUrlOrFail`
38+
- `UriTemplate::expandToPsr7Uri` and `UriTemplate::expandToPsr7UriOrFail`
39+
- `UriTemplate::expand` and `UriTemplate::expandOrFail` take a second optional parameter which represents a base URI to resolve the URI from.
3940
- Dependency to `psr/http-factory` package which is required for the package.
4041
- Support for `Uri\Rfc3986\Uri` and `Uri\Whatwg\Url`
4142

uri/UriTemplate.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use League\Uri\UriTemplate\Template;
2121
use League\Uri\UriTemplate\TemplateCanNotBeExpanded;
2222
use League\Uri\UriTemplate\VariableBag;
23+
use Psr\Http\Message\UriFactoryInterface;
24+
use Psr\Http\Message\UriInterface as Psr7UriInterface;
2325
use Stringable;
2426
use Uri\InvalidUriException;
2527
use Uri\Rfc3986\Uri as Rfc3986Uri;
@@ -150,11 +152,23 @@ public function expandToUri(iterable $variables = [], Rfc3986Uri|WhatWgUrl|Strin
150152
* @throws InvalidUrlException if the base URI cannot be converted to a Uri\Whatwg\Url instance
151153
* @throws InvalidUrlException if the resulting expansion cannot be converted to a Uri\Whatwg\Url instance
152154
*/
153-
public function expandToUrl(iterable $variables = [], WhatWgUrl|Stringable|string|null $baseUrl = null): WhatWgUrl
155+
public function expandToUrl(iterable $variables = [], Rfc3986Uri|WhatWgUrl|Stringable|string|null $baseUrl = null): WhatWgUrl
154156
{
155157
return new WhatWgUrl($this->templateExpanded($variables), $this->newWhatWgUrl($baseUrl));
156158
}
157159

160+
/**
161+
* @throws TemplateCanNotBeExpanded if the variables are invalid
162+
* @throws UriException if the resulting expansion cannot be converted to a UriInterface instance
163+
*/
164+
public function expandToPsr7Uri(
165+
iterable $variables = [],
166+
Rfc3986Uri|WhatWgUrl|Stringable|string|null $baseUrl = null,
167+
UriFactoryInterface $uriFactory = new HttpFactory()
168+
): Psr7UriInterface {
169+
return $uriFactory->createUri($this->expand($variables, $baseUrl)->toString());
170+
}
171+
158172
/**
159173
* @throws TemplateCanNotBeExpanded if the variables are invalid or missing
160174
* @throws UriException if the resulting expansion cannot be converted to a UriInterface instance
@@ -178,14 +192,29 @@ public function expandToUriOrFail(iterable $variables = [], Rfc3986Uri|WhatWgUrl
178192

179193
/**
180194
* @throws TemplateCanNotBeExpanded if the variables are invalid
181-
* @throws InvalidUriException if the base URI cannot be converted to a Uri\Whatwg\Url instance
182-
* @throws InvalidUriException if the resulting expansion cannot be converted to a Uri\Whatwg\Url instance
195+
* @throws InvalidUrlException if the base URI cannot be converted to a Uri\Whatwg\Url instance
196+
* @throws InvalidUrlException if the resulting expansion cannot be converted to a Uri\Whatwg\Url instance
183197
*/
184198
public function expandToUrlOrFail(iterable $variables = [], Rfc3986Uri|WhatWgUrl|Stringable|string|null $baseUrl = null): WhatWgUrl
185199
{
186200
return new WhatWgUrl($this->templateExpandedOrFail($variables), $this->newWhatWgUrl($baseUrl));
187201
}
188202

203+
/**
204+
* @throws TemplateCanNotBeExpanded if the variables are invalid
205+
* @throws UriException if the resulting expansion cannot be converted to a UriInterface instance
206+
*/
207+
public function expandToPsr7UriOrFail(
208+
iterable $variables = [],
209+
Rfc3986Uri|WhatWgUrl|Stringable|string|null $baseUrl = null,
210+
UriFactoryInterface $uriFactory = new HttpFactory()
211+
): Psr7UriInterface {
212+
return $uriFactory->createUri($this->expandOrFail($variables, $baseUrl)->toString());
213+
}
214+
215+
/**
216+
* @throws InvalidUrlException
217+
*/
189218
private function newWhatWgUrl(Rfc3986Uri|WhatWgUrl|Stringable|string|null $url = null): ?WhatWgUrl
190219
{
191220
return match (true) {
@@ -196,13 +225,16 @@ private function newWhatWgUrl(Rfc3986Uri|WhatWgUrl|Stringable|string|null $url =
196225
};
197226
}
198227

199-
private function newRfc3986Uri(Rfc3986Uri|WhatWgUrl|Stringable|string|null $url = null): ?Rfc3986Uri
228+
/**
229+
* @throws InvalidUriException
230+
*/
231+
private function newRfc3986Uri(Rfc3986Uri|WhatWgUrl|Stringable|string|null $uri = null): ?Rfc3986Uri
200232
{
201233
return match (true) {
202-
null === $url => null,
203-
$url instanceof Rfc3986Uri => $url,
204-
$url instanceof WhatWgUrl => new Rfc3986Uri($url->toAsciiString()),
205-
default => new Rfc3986Uri((string) $url),
234+
null === $uri => null,
235+
$uri instanceof Rfc3986Uri => $uri,
236+
$uri instanceof WhatWgUrl => new Rfc3986Uri($uri->toAsciiString()),
237+
default => new Rfc3986Uri((string) $uri),
206238
};
207239
}
208240

0 commit comments

Comments
 (0)