File: extension.md

package info (click to toggle)
php-league-uri-src 7.5.1-7
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,712 kB
  • sloc: php: 16,698; javascript: 127; makefile: 43; xml: 36
file content (176 lines) | stat: -rw-r--r-- 5,033 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
---
layout: default
title: URIs extension
redirect_from:
    - /5.0/uri/extension/
---

# Creating other URI objects

<p class="message-warning">Starting with version <code>1.1.0</code> all URI objects are defined in the <code>League\Uri</code> namespace. The <code>League\Uri\Schemes</code> namespace is deprecated and will be removed in the next major release.</p>

## Creating a simple URI object

Let say you want to create a `telnet` class to handle telnet URI. You just need to extends the <code>League\Uri\AbstractUri</code> object and add telnet specific validation features to your class. Here's a quick example that you can further improve.

~~~php
<?php

namespace Example;

use League\Uri\AbstractUri;

class Telnet extends AbstractUri
{
    /**
     * Supported Schemes with their associated port
     *
     * This property override the Parent supported_schemes empty array
     *
     * @var array
     */
    protected static $supported_schemes = [
        'telnet' => 23,
    ];

    /**
     * Validate any changes made to the URI object
     *
     * This method override the Parent isValidUri method
     * When it returns false a InvalidArgumentException is thrown
     *
     * @return bool
     */
    protected function isValidUri()
    {
        return null === $this->fragment
            && '' !== $this->host
            && (null === $this->scheme || isset(static::$supported_schemes[$this->scheme]))
            && !('' != $this->scheme && null === $this->host);
    }
}
~~~

And now you can easily make it works against any `telnet` scheme URI

~~~php
<?php

use Example\Telnet;

$uri = Telnet::createFromString('TeLnEt://example.com:23/Hello%20There'):
echo $uri; //return telnet://example.com/Hello%20There
Telnet::createFromString('http://example.org'):
//will throw an League\Uri\UriException
~~~

## Advance URI Object creation

Since each URI specific schemes follow its own validation rules they need their own class. The library can help you speed up your process to create such class. As an example we will implement the `mailto` scheme.

`mailto` URIs are specific in the fact that :

- they do not have any authority part and fragment components;
- their paths are made of urlencoded emails separated by a comma;

We simply need to add:

- the path validating methods
- enforce the URI specific validation state

~~~php
<?php

namespace Example;

use League\Uri\AbstractUri;
use League\Uri\UriException;

class Mailto extends AbstractUri
{
    /**
     * Validate any changes made to the URI object
     *
     * This method override the Parent isValidUri method
     * When it returns false an InvalidArgumentException is thrown
     *
     * @return bool
     */
    protected function isValidUri()
    {
        return 'mailto' === $this->scheme
            && null === $this->fragment
            && null === $this->authority
    }

    /**
     * Filter the Path component
     *
     * This method override the Parent filterPath method
     *
     * @param string $path
     *
     * @throws UriException If the path is not compliant
     *
     * @return string
     */
    protected function filterPath($path)
    {
        if ('' == $path) {
            throw new UriException('the submitted path can not be empty');
        }

        $emails = array_map('rawurldecode', explode(',', $path));
        $emails = array_map('trim', $emails);
        $emails = array_filter($emails);
        if (empty($emails)) {
            throw new UriException('the submitted path contains empty emails');
        }

        $verif = filter_var($emails, FILTER_VALIDATE_EMAIL, FILTER_REQUIRE_ARRAY);
        if ($emails !== $verif) {
            throw new UriException('the submitted path contains invalid emails');
        }

        return $path;
    }

    /**
     * A specific named constructor to speed up
     * creating a new instance from a collection of mails
     *
     * @param string[] $emails
     *
     * @return static
     */
    public static function createFromEmails(array $emails)
    {
        $verif = filter_var($emails, FILTER_VALIDATE_EMAIL, FILTER_REQUIRE_ARRAY);
        if ($emails !== $verif) {
            throw new Exception('the submitted emails are invalid');
        }

        $path = implode(',', array_map('rawurlencode', $emails));

        return new static::createFromComponents(['scheme' => 'mailto', 'path' => $path]);
    }
}
~~~

Et voilĂ ! You can already do this:

~~~php
<?php

use Example\Mailto;

$subject = http_build_query(['subject' => 'Hello World!'], '', '&', PHP_QUERY_RFC3986);
$mailto = Mailto::createFromEmails(['foo@example.com', 'info@thephpleague.com'])
    ->withQuery($subject);
echo $mailto;
//displays 'mailto:foo@example.com,info@thephpleague.com?subject=Hello%20World%21';
~~~

## URI manipulations

Of course you are free to add more methods to fulfill your own requirements. But remember that the URI common API and <a href="/5.0/manipulations/middlewares/">the URI middlewares</a> are already usable with these simple steps.