@@ -48,7 +48,7 @@ echo Modifier::from($uriString)->mergeQuery($queryToMerge);
4848
4949In addition to merging the query, ` mergeQuery ` has:
5050
51- - enforced ` RFC3986 ` encoding throughout the modifications;
51+ - enforced standard compliant encoding throughout the modifications;
5252- not mangle your data during merging;
5353- returned a valid URI object;
5454
@@ -114,6 +114,126 @@ $uri->toHtmlAnchor('My Shop', ['class' => ['text-center', 'text-6xl']]);
114114<p class =" message-info " >The <code >toDisplayString()</code >, <code >toMarkdownAnchor()</code > and <code >toHtmlAnchor()</code > methods are available since version <code >7.6.0</code >.</p >
115115<p class =" message-notice " >The <code >getUri()</code >, <code >getUriString()</code > and <code >getIdnUriString()</code > methods are deprecated since version <code >7.6.0</code >.</p >
116116
117+ ## General Modifiers
118+
119+ <p class =" message-notice " >available since version <code >7.6.0</code ></p >
120+
121+ With the addition of (2) two new native PHP URI representations, it can become complex to
122+ remember which URI method to use and which type of argument is expected. The ` Modifier ` can
123+ ease this by wrapping the underlying URI object is a common and predicable public API.
124+
125+ Apart from partially modifying an URI component, since version ` 7.6.0 ` , you can directly:
126+
127+ - completely change a URI component;
128+ - resolve URIs;
129+ - normalize URIs;
130+
131+ ### Modifier complete URI component replacement
132+
133+ The ` Modifier ` class will perform some sanity checks and/or formatting before
134+ handing over the changed value to the underlying object to perform the action.
135+ Unless the input data is invalid, the exception thrown will be the ones from the
136+ underlying URI object.
137+
138+ Here's an example:
139+
140+ ``` php
141+ use Uri\Rfc3986\Uri;
142+
143+ echo new Uri('http://example.com/foo/bar')
144+ ->withHost('bébé.be')
145+ ->toString(), PHP_EOL;
146+ // this will throw because
147+ // the host contains unsupported characters
148+ // according to RFC3986
149+ ```
150+
151+ In contrast, when using the ` Modifier ` the result is different:
152+
153+ ``` php
154+ use League\Uri\Modifier;
155+ use Uri\Rfc3986\Uri;
156+
157+ echo Modifier::from(new Uri('http://example.com/foo/bar'))
158+ ->withHost('bébé.be')
159+ ->uri()
160+ ->toString(), PHP_EOL;
161+ // the `uri()` methods returns a valid Uri\Rfc3986\Uri instance
162+ // its `toString()` method returns http://xn--bb-bjab.be/foo/bar
163+ // the modifier has converted the host into its ascii representation
164+ // to avoid the exception to be thrown.
165+ ```
166+
167+ ### URI resolution
168+
169+ Apart from modifying a URI component, the ` Modifier ` can also normalize or
170+ resolve URI. Resolving and Normalizing URI is supported by ` League\Uri\Uri ` ,
171+ and PHP's native URI object ** but** not by PSR-7 ` UriInterface ` and the
172+ public API diverge. using the ` Modifier ` class you get a single method for
173+ all the URI objects and add the missing support for any PSR-7 implementing class
174+
175+ ``` php
176+ use Uri\Whatwg\Url;
177+
178+ echo new Url('http://example.com/foo/bar')
179+ ->resolve('./../bar')
180+ ->toAsciiString(), PHP_EOL;
181+ // returns http://example.com/bar
182+ // there is no equivalent in PSR-7
183+ ```
184+ using the ` Modifier ` you can do the following:
185+
186+ ``` php
187+ use League\Uri\Modifier;
188+ use GuzzleHttp\Psr7\Utils;
189+
190+ echo Modifier::from(Utils::uriFor('http://example.com/foo/bar'))
191+ ->resolve('./../bar')
192+ ->uri()
193+ ->__toString(), PHP_EOL;
194+ // `uri()` returns a Guzzle PSR-7 URI object
195+ // returns "http://example.com/bar"
196+ ```
197+
198+ ### URI normalization
199+
200+ RFC3986 and WHATWG URL specification both allow normalizing URIs. But both
201+ specification do it in a different way and capacity. Normalization is
202+ mandatory when using a WHATWG URL but optional with RFC3986. It is
203+ not covered in PSR-7. Which again may leave the developer in a challenging
204+ situation. To ease developer experience, the ` Modifier ` class exposes a
205+ new ` normalize ` method which guarantee normalization regardless of the
206+ underlying URI object.
207+
208+ ``` php
209+ use League\Uri\Url;
210+ use Uri\Rfc3986\Uri as Rfc3986Uri;
211+ use Uri\Whatwg\Url as WhatwgUrl;
212+
213+ $uriString = 'HttP://ExamPle.com/./../foo/bar';
214+ echo (new WhatwgUrl($uriString))->toAsciiString(), PHP_EOL;
215+ echo (new Rfc3986Uri($uriString))->toString(), PHP_EOL;
216+ echo Uri::new($uriString)->normalize()->toString(), PHP_EOL;
217+ // returns 'http://example.com/foo/bar
218+ // PSR-7 UriInterface does not have a method for that
219+ ```
220+
221+ Again using the ` Modifier ` class you will get a unified and predicable returned URI
222+
223+ ``` php
224+ use League\Uri\Modifier;
225+ use GuzzleHttp\Psr7\Utils;
226+
227+ $uriString = 'HttP://ExamPle.com/./../foo/bar';
228+ echo Modifier::from(Utils::uriFor($uriString))
229+ ->normalize()
230+ ->uri()
231+ ->__toString();
232+ // returns 'http://example.com/foo/bar
233+ ```
234+
235+ ## Partial Modifiers
236+
117237### Available modifiers
118238
119239Under the hood the ` Modifier ` class intensively uses the [ URI components objects] ( /components/7.0/ )
@@ -202,12 +322,10 @@ to apply the following changes to the submitted URI.
202322 <li><a href="#modifierwithscheme">withScheme</a></li>
203323 <li><a href="#modifierwithuserinfo">withUserInfo</a></li>
204324 <li><a href="#modifierwithport">withPort</a></li>
205- <li><a href="#modifierresovlve">URI resolve</a></li>
206325</ul >
207326</div >
208327</div >
209328
210-
211329## Query Modifiers
212330
213331Following modifiers update and normalize the URI query component.
@@ -1086,42 +1204,59 @@ echo Modifier::from($uri)
10861204// display ":~:text=foo,bar&text=yes"
10871205~~~
10881206
1089- ## General modifications
1207+ ## Other available modifiers
1208+
1209+ ### Modifier::withUserInfo
10901210
10911211<p class =" message-notice " >available since version <code >7.6.0</code ></p >
10921212
1093- To ease modifying URI since version ` 7.6.0 ` you can directly access:
1213+ Allow modifying the user info component
10941214
1095- - the modifier methods from the underlying URI object or
1096- - resolve an URI base on the underlying URI object rules or
1097- - normalize an URI base on the underlying URI object rules.
1215+ ~~~ php
1216+ use League\Uri\Modifier;
1217+ use Uri\Rfc3986\Uri;
10981218
1099- The difference being that the ` Modifier ` class will perform the correct conversion
1100- to handle the differences between URI object signature.
1219+ $uri = new Uri("http://www.example.com/path/to/the/sky");
1220+ echo Modifier::from($uri)
1221+ ->withUserInfo(username: null, password: 'pa@ss')
1222+ ->uri()
1223+ ->getUserInfo();
1224+ // display ":pa%40ss"
1225+ // for information the Uri::withUserInfo method only takes a single variable.
1226+ ~~~
11011227
1102- ``` php
1228+ ### Modifier::withScheme
1229+
1230+ <p class =" message-notice " >available since version <code >7.6.0</code ></p >
1231+
1232+ Allow modifying the URI scheme
1233+
1234+ ~~~ php
1235+ use League\Uri\Modifier;
1236+ use Uri\Rfc3986\Uri;
1237+
1238+ $uri = new Uri("http://www.example.com/path/to/the/sky");
1239+ $newUri = Modifier::from($uri)->withScheme('HtTp')->uri();
1240+ $newUri->getRawScheme(); // returns 'HtTp'
1241+ $newUri->getScheme(); // returns 'http'
1242+ ~~~
1243+
1244+ The stored scheme value will depend on the underlying URI object.
1245+
1246+ ### Modifier::withPort
1247+
1248+ <p class =" message-notice " >available since version <code >7.6.0</code ></p >
1249+
1250+ Allow modifying the URI port. Added for completeness. This
1251+ method works the same across all the URI objects, but may throw
1252+ depending on the restriction from the underlying URI object on
1253+ port range.
1254+
1255+ ~~~ php
11031256use League\Uri\Modifier;
11041257use Uri\WhatWg\Url;
11051258
1106- $foo = '';
1107- echo Modifier::from('http://bébé.be')
1108- ->when(
1109- '' !== $foo,
1110- fn (Modifier $uri) => $uri->withQuery('fname=jane&lname=Doe'), //on true
1111- fn (Modifier $uri) => $uri->mergeQueryParameters(['fname' => 'john', 'lname' => 'Doe']), //on false
1112- )
1113- ->appendSegment('toto')
1114- ->addRootLabel()
1115- ->prependLabel('shop')
1116- ->appendQuery('foo=toto&foo=tata')
1117- ->withFragment('chapter1')
1118- ->toDisplayString();
1119- // returns 'http://shop.bébé.be./toto?fname=john&lname=Doe&foo=toto&foo=tata#chapter1';
1120-
1121- echo Modifier::from(new Url('http://bébé.be/../do/it'))
1122- ->appendSegment('toto')
1123- ->resolve('./foo/../bar')
1124- ->uri()
1125- ->toAsciiString(), PHP_EOL;
1126- // returns http://xn--bb-bjab.be/do/it/bar
1127- ```
1259+ $uri = new Url("http://www.example.com/path/to/the/sky");
1260+ $newUri = Modifier::from($uri)->withPort(433)->uri();
1261+ $newUri->getPort(); // returns 433
1262+ ~~~
0 commit comments