Библиотека с открытым исходным кодом.
👉 Navigator - это генератор url. Работает с внутренней навигацией приложения и способен генерировать URL-адреса на внешние ресурсы. Внутренняя навигация осуществляется на основе именованных определений маршрутов. Именованные маршруты дают возможность удобно создавать URL-адреса, не привязываясь к домену или к определению маршрута.
Библиотека предназначена для приложений использующих в своем коде маршрутизатор FastRoute. FastRoute использует определения маршрутов на основе регулярных выражений, а Navigator создает URL-адреса соответствующие этим определениям маршрутов.
Для постоянства кода определениям маршрутов назначаются имена.
имя определение
маршрута маршрута
/‾‾‾‾‾‾‾\ /‾‾‾‾‾‾‾‾‾‾‾\
'user/view' => '/user/{id:\d+}',
Это позволяет манипулировать URL-адресами без внесения изменений в существующий код. Например, для создания URL-адреса
именованного определения 'user' => '/user/{id:\d+}'
, можно использовать следующий код:
/** relative url */
echo $urlBuilder->build('/user', ['id' => 100]); # /user/100
/** absolute url */
echo $urlBuilder->build('/user', ['id' => 100], true); # http://mydomain.ru/user/100
Если по какой-либо причине потребуется изменить адрес с /user/100
на /employee/100
, вам нужно будет просто изменить
настройку маршрута с '/user/{id:\d+}'
на '/employee/{id:\d+}'
. После этого код выше будет создавать относительный
URL-адрес /employee/100
и абсолютный http://mydomain.ru/employee/100
.
В объекте класса Navigator\UrlBuilder
два метода генерации URL: build
и buildExternal
. Метод build
используется
для навигации внутри приложения, а buildExternal
создает URL для внешних ресурсов и может генерировать только
абсолютные URL-адреса.
Предпочтительный способ установки - через composer.
Запустите команду
php composer require vinogradsoft/navigator "^1.0"
Требуется PHP 8.0 или новее.
<?php
use Navigator\ArrayRulesProvider;
use Navigator\UrlBuilder;
require_once dirname(__DIR__, 1) . '/vendor/autoload.php';
$urlBuilder = new UrlBuilder(
'https://vinograd.soft',
new ArrayRulesProvider([
'user' => '/user[/{var_name}]',
// many other route definitions in key-value format.
])
);
echo $urlBuilder->build('/user', null, true), '<br>'; # https://vinograd.soft/user
echo $urlBuilder->build('/user', ['var_name' => 'var_value'], true), '<br>'; # https://vinograd.soft/user/var_value
echo $urlBuilder->build('user', ['var_name' => 'var_value'], true), '<br>'; # https://vinograd.soft/user/var_value
echo $urlBuilder->build('/user', ['var_name' => 'var_value']), '<br>'; # /user/var_value
echo $urlBuilder->build('user', ['var_name' => 'var_value']), '<br>'; # user/var_value
Конструктор имеет шесть параметров, пожалуй самые главные первые два.
Первым параметром идет $baseUrl
- в данном примере его значение равно 'https://vinograd.soft'
- это базовый URL,
который используется для генерации абсолютных URL-адресов внутри приложения.
Второй параметр $rulesProvider
принимает экземпляр реализации интерфейса Navigator\RulesProvider
.
В примере используется реализация Navigator\ArrayRulesProvider
, которая работает с обычным массивом
зарегистрированных маршрутов. По сути это источник именованных определений маршрутов.
Параметром $name
вы передаете имя маршрута. На основе значения этого параметра система понимает с каким определением
работает и преобразует его в URL-адрес. В примере используется два случая 'user'
и '/user'
.
Стоит отметить, что символ “/” в начале передаваемого имени никак не влияет на поиск маршрута, он указывает системе, что
данный символ должен быть включен в начало генерируемого URL-адреса. Система распознает этот символ затем
осуществляет поиск маршрута по имени, исключая из него данный символ. После этого “/” используется системой как
индикатор того, что его необходимо включить в начало формируемого относительного URL-адреса.
Может быть массивом настроек заполнителей
или null
.
Из примера, $urlBuilder
работает с определением маршрута '/user[/{var_name}]'
, где var_name
это динамическая
часть,
другими словами переменная.
В метод build
мы передали такой массив ['var_name' => 'var_value']
, где 'var_name'
переменная из определения
маршрута, а 'var_value'
ее значение, т.е. то чем 'var_name'
в результате будет заменена, в нашем случае результат
для абсолютного URL-адреса такой https://vinograd.soft/user/var_value
.
NULL используется в случаях генерации статических URL, которым не нужны настройки в директориях пути, такому как это
определение 'user' => '/user'
.
Пример:
$urlBuilder = new UrlBuilder(
'https://vinograd.soft',
new ArrayRulesProvider([
'user' => '/user/profile',
])
);
echo $urlBuilder->build('/user', null, true); # https://vinograd.soft/user/profile
Этот булевый параметр указывает системе, какой URL-адрес создавать: абсолютный или относительный. Передача true
приведет к созданию абсолютного адреса, в противном случае будет создан относительный адрес. Значение по умолчанию
равно false
.
Имена определений не имеют жесткого формата, поэтому какие давать имена зависит от вас.
Вы можете использовать формат <контроллер>/<действие>
пример: post/view
.
Или добавлять в начало название модуля blog/post/view
.
Важно запомнить одно, нельзя чтобы первым символом был /
. Такое имя не правильное /blog/post/view
в моменте
генерации URL методом build
, маршрут с таким именем не будет найден, поскольку система будет его искать без
символа /
в начале, затем будет выброшено исключение Navigator\RoutConfigurationException
.
Пример правильного имени маршрута:
new ArrayRulesProvider([
'blog/post/view' => '/post/{id:\d+}',
]);
Пример НЕДОПУСТИМОГО имени маршрута:
new ArrayRulesProvider([
// Not working warrant /blog/post/view
'/blog/post/view' => '/post/{id:\d+}',
]);
В именах совсем не обязателен символ
/
, имя может быть и такимblog.post.view
или каким-то другим не имеющим разделителей вовсе.
Как формировать маршруты вы можете прочитать в документации к библиотеке FastRoute.
|------------------------------:src--------------------------------------------------|
| :path ? # |
| /‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\ /‾‾‾‾‾‾‾‾‾\ /‾‾‾‾‾‾\|
|http://grigor:[email protected]:8080/path/to/resource.json?query=value#fragment|
\__/ \___/ \_____/ \___________/ \__/ \__/
:scheme :user :password :host :port :suffix
Не все заполнители доступны для обоих методов генерации. Таблица ниже показывает доступность каждого заполнителя и тип данных значения.
Заполнитель | Доступность для метода build |
Доступность для метода buildExternal |
Тип |
---|---|---|---|
название переменной из определения |
ДА | НЕТ | string/int тип bool - для переменных без фигурных скобок{} . |
:src |
НЕТ | ДА | string |
:scheme |
НЕТ | ДА | string |
:user |
НЕТ | ДА | string |
:password |
НЕТ | ДА | string |
:host |
НЕТ | ДА | string |
:port |
НЕТ | ДА | string |
:path |
НЕТ | ДА | string/array |
:suffix |
НЕТ | ДА | string |
? |
ДА | ДА | string/array |
# |
ДА | ДА | string |
:strategy |
ДА | ДА | string |
:idn |
ДА | ДА | bool |
Для начала сконфигурируем $urlBuilder
таким образом:
$urlBuilder = new UrlBuilder(
'https://vinograd.soft',
new ArrayRulesProvider([
'user' => '/user[/{var_name}]',
'about' => '/about[.html]',
])
);
Не обязательные параметры в определениях не обрамленные в фигурные скобки имеют тип заполнителя
bool
.
Страница "about" имеет в определении суффикс - не обязательный параметр .html
без фигурных скобок. Требуется
сгенерировать URL с этим суффиксом.
echo $urlBuilder->build('about', ['.html' => true], true); # https://vinograd.soft/about.html
Сгенерируйте абсолютный URL-адрес используя необязательный заполнитель для определения 'user' => '/user[/{var_name}]'
.
echo $urlBuilder->build('/user', ['var_name' => 'my_unique_value'], true);
# https://vinograd.soft/user/my_unique_value
Требуется сгенерировать относительный URL-адрес с символом /
в начале для определения
'user' => '/user[/{var_name}]'
.
echo $urlBuilder->build('/user', ['var_name' => 'my_unique_value']); # /user/my_unique_value
Создайте относительный URL-адрес без символа /
в начале для определения 'user' => '/user[/{var_name}]'
.
echo $urlBuilder->build('user', ['var_name' => 'my_unique_value']); # user/my_unique_value
Определение 'user' => '/user[/{var_name}]'
имеет не обязательный параметр var_name
. Нужно сгенерировать абсолютный
URL-адрес без этого параметра.
echo $urlBuilder->build('user', null, true); # https://vinograd.soft/user
В приложении есть переменная в которую записан URL-адрес внешнего ресурса. Нужно внести в URL-адрес несколько изменений:
- изменить его схему с
http
наftp
- добавить имя пользователя
grigor
и парольpassword123
- изменить порт на
21
.
$externalAddress = 'http://another.site:8080/path/to/resource';
echo $urlBuilder->buildExternal([
':src' => $externalAddress,
':scheme' => 'ftp',
':user' => 'grigor',
':password' => 'password123',
':port' => '21'
]);
# ftp://grigor:[email protected]:21/path/to/resource
Добавьте путь blog/post/41
к URL-адресу главной странице другого сайта http://another.site
.
echo $urlBuilder->buildExternal([
':src' => 'http://another.site',
':path' => ['blog', 'post', 41],
]);
# http://another.site/blog/post/41
Измените схему URL-адреса http://another.site
с http
на https
.
echo $urlBuilder->buildExternal([
':src' => 'http://another.site',
':scheme' => 'https',
]);
# https://another.site
Создайте URL-адрес https://another.site/path/to/resource
из имеющихся в приложении частей со схемой https
.
echo $urlBuilder->buildExternal([
':scheme' => 'https',
':host' => 'another.site',
':path' => ['path', 'to', 'resource'],
]);
# https://another.site/path/to/resource
Добавьте имя пользователя user
для URL-адреса http://another.site
.
echo $urlBuilder->buildExternal([
':src' => 'http://another.site',
':user' => 'user'
]);
# http://[email protected]
Этот заполнитель работает только в паре с заполнителем
:user
. Часть:user
либо должна присутствовать в исходном URL-адресе передаваемом в заполнителе:src
, либо должен передаваться в паре с заполнителем:password
, если:user
в URL его не окажется, будет выброшено исключениеNavigator\BadParameterException
.
Добавьте имя пользователя grigor
и пароль password123
для URL-адреса ftp://another.site:21
.
echo $urlBuilder->buildExternal([
':src' => 'ftp://another.site:21',
':user' => 'grigor',
':password' => 'password123'
]);
# ftp://grigor:[email protected]:21
Заполнитель
:host
используется в паре с заполнителем:scheme
. В случае когда вы не используете заполнитель:src
, хотите создать URL-адрес из частей, то:host
и':scheme'
будут обязательными, при отсутствии любого из них будет выброшено исключениеNavigator\BadParameterException
.:host
единственный заполнитель который не переопределяет свой участок в URL-адресе переданным заполнителем:src
.
Требуется создать URL-адрес http://another.site
.
echo $urlBuilder->buildExternal([
':scheme' => 'http',
':host' => 'another.site'
]);
# http://another.site
Создайте URL-адрес http://another.site
с портом 5000
.
echo $urlBuilder->buildExternal([
':scheme' => 'http',
':host' => 'another.site',
':port' => '5000'
]);
# http://another.site:5000
Требуется создать URL-адрес https://another.site/path/to
используя значение заполнителя с типом array
.
echo $urlBuilder->buildExternal([
':src' => 'https://another.site',
':path' => ['path', 'to']
]);
# https://another.site/path/to
Сгенерируйте URL-адрес https://another.site/path/to
используя значение заполнителя с типом string
.
echo $urlBuilder->buildExternal([
':src' => 'https://another.site',
':path' => 'path/to'
]);
# https://another.site/path/to
С суффиксами есть один нюанс, если вы передаете URL-адрес с суффиксом средствами заполнителя
:src
вы не сможете его переопределить заполнителем:suffix
, вы можете его только добавить, поскольку суффиксом может быть любая стока, он не анализируется и будет являться частью path.
Добавьте к URL-адресу https://another.site/path/to
расширение .html
.
echo $urlBuilder->buildExternal([
':src' => 'https://another.site',
':path' => 'path/to',
':suffix' => '.html'
]);
# https://another.site/path/to.html
Добавьте суффикс -city
к URL-адресу https://another.site/path/to?q=value#news
.
echo $urlBuilder->buildExternal([
':src' => 'https://another.site/path/to?q=value#news',
':suffix' => '-city'
]);
# https://another.site/path/to-city?q=value#news
Добавьте параметр s
со значением Hello world
URL-адресу https://another.site
.
echo $urlBuilder->buildExternal([':src' => 'https://another.site', '?' => ['s' => 'Hello world']]);
# https://another.site/?s=Hello%20world
В системе есть подготовленный параметр s=Hello world
нужно добавить его к URL-адресу https://another.site
.
echo $urlBuilder->buildExternal([
':src' => 'https://another.site',
'?' => 's=Hello world'
]);
# https://another.site/?s=Hello%20world
Требуется создать URL-адрес для ссылки на результаты поиска другого сайта https://another.site
со следующими
параметрами:
[
'search' => [
'blog' => [
'category' => 'news',
'author' => 'Grigor'
]
]
]
Код:
echo $urlBuilder->buildExternal([
':src' => 'https://another.site',
'?' => [
'search' => [
'blog' => [
'category' => 'news',
'author' => 'Grigor'
]
]
]
]);
# https://another.site/?search%5Bblog%5D%5Bcategory%5D=news&search%5Bblog%5D%5Bauthor%5D=Grigor
Задача сформировать адрес для ссылки на документацию библиотеки vinogradsoft/compass
, параграф quick-start
.
echo $urlBuilder->buildExternal([
':src' => 'https://github.com/vinogradsoft/compass',
'#' => 'quick-start'
]);
# https://github.com/vinogradsoft/compass#quick-start
Для использования стратегий создания URL-адресов нужно либо реализовать интерфейс
Compass\UrlStrategy
, либо наследоваться от классаCompass\DefaultUrlStrategy
. Более подробно о принципах работы стратегий можно прочитать в документации к библиотеке Compass.
Задача сделать стратегию для генерации URL-адресов реферальных ссылок с параметром refid
равному 222
.
Код стратегии:
<?php
namespace <your namespace>;
use Compass\DefaultUrlStrategy;
use Compass\Url;
class ReferralUrlStrategy extends DefaultUrlStrategy
{
/**
* @inheritDoc
*/
public function updateQuery(array $items): string
{
$items['refid'] = 222;
return http_build_query($items, '', '&', PHP_QUERY_RFC3986);
}
/**
* @inheritDoc
*/
public function forceUnlockMethod(
bool &$schemeState,
int &$authoritySate,
int &$relativeUrlState,
array $items,
array $pathItems,
array $queryItems,
bool $updateAbsoluteUrl,
?string $suffix = null
): void
{
$relativeUrlState &= ~Url::QUERY_STATE;
}
}
Добавим стратегию в конструктор $urlBuilder
:
$urlBuilder = new UrlBuilder(
'https://vinograd.soft',
new ArrayRulesProvider([
'user' => '/user[/{var_name}]'
]),
['referral' => new ReferralUrlStrategy()]
);
Генерируем URL-адрес:
echo $urlBuilder->buildExternal([
':src' => 'https://another.site/path/to/resource',
':strategy' => 'referral'
]);
# https://another.site/path/to/resource?refid=222
Возьмем стратегию из Примера 1 этого параграфа, и сделаем ее стратегией по умолчанию для генерации внешних URL-адресов.
Заменим в экземпляре класса Compass\Url
стратегию и передадим его в конструктор нашего $urlBuilder
пятым
параметром ($externalUrl
):
$externalUrl = Url::createBlank();
$externalUrl->setUpdateStrategy(new ReferralUrlStrategy());
$urlBuilder = new UrlBuilder(
'https://vinograd.soft',
new ArrayRulesProvider([
'user' => '/user[/{var_name}]'
]),
[],
null,
$externalUrl
);
Генерируем URL-адрес:
echo $urlBuilder->buildExternal([
':src' => 'https://another.site/path/to/resource'
]);
# https://another.site/path/to/resource?refid=222
Задача конвертировать URL-адрес https://россия.рф
в panycode.
echo $urlBuilder->buildExternal([':src' => 'https://россия.рф', ':idn' => true]);
# https://xn--h1alffa9f.xn--p1ai
php composer tests
Пожалуйста, смотрите ВКЛАД для получения подробной информации.
Лицензия MIT (MIT). Пожалуйста, смотрите файл лицензии для получения дополнительной информации.