Работа с адресами страниц в PHP: классы и функции
Подходы к обработке URL в PHP
Как создать собственный класс для управления URL?
Создание собственного класса Url позволяет инкапсулировать логику разбора, сборки и модификации URL. Это удобно для проектов, где требуется частая работа с адресами, и нет необходимости в полной реализации стандарта URI.
class Url {
private string $scheme;
private string $host;
private ?int $port;
private string $path;
private array $query;
private ?string $fragment;
public function __construct(string $url) {
$parts = parse_url($url);
$this->scheme = $parts['scheme'] ?? 'http';
$this->host = $parts['host'] ?? '';
$this->port = $parts['port'] ?? null;
$this->path = $parts['path'] ?? '/';
parse_str($parts['query'] ?? '', $this->query);
$this->fragment = $parts['fragment'] ?? null;
}
public function getFullUrl(): string {
$query = http_build_query($this->query);
$url = $this->scheme . '://' . $this->host;
if ($this->port) $url .= ':' . $this->port;
$url .= $this->path;
if ($query) $url .= '?' . $query;
if ($this->fragment) $url .= '#' . $this->fragment;
return $url;
}
public function setQueryParam(string $key, $value): void {
$this->query[$key] = $value;
}
}
Php создание ссылки (создание ссылки в php)
Класс принимает строку URL в конструкторе, использует parse_url для разбора и parse_str для параметров запроса. Метод getFullUrl собирает URL обратно. Это позволяет легко изменять параметры, например, добавлять utm-метки.
Типичные проблемы: некорректная обработка относительных URL (нет хоста), кодирование спецсимволов в query (лучше использовать http_build_query), отсутствие проверки валидности URL. Решение: добавить валидацию через filter_var($url, FILTER_VALIDATE_URL).
Как выполнить разбор и сборку URL без классов?
Встроенные функции parse_url и http_build_query – самый простой способ. Подходит для одноразовых операций или скриптов без строгой архитектуры.
$url = 'http://example.com/path?name=Иван#section';
$parts = parse_url($url);
echo $parts['scheme']; // http
parse_str($parts['query'] ?? '', $query);
echo $query['name']; // Иван
Js php url (javascript и php url)
Функции возвращают ассоциативные массивы. Для сборки используйте http_build_query, который автоматически кодирует UTF-8.
Типичные ошибки: путаница с массивами query (неправильное имя ключа), потеря кодировки при ручной сборке. Решение: всегда использовать http_build_query для создания строки запроса.
Как получить полный функционал для работы с URI?
Библиотека league/uri предоставляет строгий объектно-ориентированный интерфейс, соответствующий стандарту RFC 3986. Включает проверку, нормализацию, изменение компонентов.
use League\Uri\Uri;
$uri = Uri::createFromString('http://example.com/path?q=test');
$newUri = $uri->withScheme('https')->withQuery('q=php');
echo $newUri; // https://example.com/path?q=php
Php url (url в php)
Установка: composer require league/uri. Позволяет работать с IPv6, IDN, относительными ссылками.
Проблемы: зависимость от внешней библиотеки, может быть избыточной для простых задач. Решение: взвесить необходимость и альтернативы.
Как работать с URL в контексте PSR-7?
Интерфейс Psr\Http\Message\UriInterface определён в PSR-7. Реализации (например, в Guzzle Http) позволяют единообразно манипулировать URL в HTTP-сообщениях.
use GuzzleHttp\Psr7\Uri;
$uri = new Uri('http://example.com/path');
$modified = $uri->withPort(8080)->withUserInfo('admin', 'pass');
echo (string) $modified;
Методы возвращают новые объекты (immutable). Используется в фреймворках, клиентах API.
Типичные ошибки: забыть присвоить результат (объект неизменяем), неправильное понимание unicode. Решение: всегда присваивать результат вызова with*.
Расширенные примеры работы с URL
Манипуляции с query-параметрами через собственный класс
Создадим экземпляр класса Url, добавим несколько параметров и удалим один.
$url = new Url('http://shop.com/products?page=2&sort=price');
$url->setQueryParam('page', 3);
$url->removeQueryParam('sort');
$url->setQueryParam('utm_source', 'google');
echo $url->getFullUrl();
http://shop.com/products?page=3&utm_source=google
Пояснение: методы класса инкапсулируют изменение массива query и последующую сборку. Обратите внимание, что метод removeQueryParam не был показан в базовом классе, его легко добавить.
Нормализация URL (удаление фрагмента и порта)
Библиотека league/uri позволяет удалить фрагмент и сбросить порт до стандартного.
use League\Uri\Uri;
$uri = Uri::createFromString('https://example.com:443/path#frag');
$normalized = $uri->withoutFragment()->withPort(null);
echo $normalized;
https://example.com/path
Пояснение: библиотека знает, что порт 443 соответствует HTTPS, и при установке null удаляет его. Метод withoutFragment убирает якорь.
Извлечение доменного имени с поддоменами
Используем parse_url и разбиваем хост на части.
$url = 'https://sub.domain.com/page';
$host = parse_url($url, PHP_URL_HOST);
$parts = explode('.', $host);
echo 'TLD: ' . end($parts) . ', домен: ' . $parts[count($parts)-2];
TLD: com, домен: domain
Пояснение: работает только для доменов второго уровня, для .co.uk потребуется более сложная логика, которую предоставляет класс Pdp\Rules из библиотеки jeremykendall/php-domain-parser.
Кодирование и декодирование спецсимволов в пути
Функции rawurlencode и rawurldecode обрабатывают компоненты пути.
$path = '/статья/о PHP';
$encoded = rawurlencode($path); // неверно - кодирует слеши
$pathParts = explode('/', $path);
$encodedParts = array_map('rawurlencode', $pathParts);
$cleanPath = implode('/', $encodedParts);
echo $cleanPath;
/%D1%81%D1%82%D0%B0%D1%82%D1%8C%D1%8F/%D0%BE%20PHP
Пояснение: важно кодировать только сегменты, а не весь путь, чтобы сохранить слеши как разделители.
Сравнение двух URL на равенство (игнорируя регистр и порядок параметров)
С помощью PSR-7 Uri можно нормализовать перед сравнением.
use GuzzleHttp\Psr7\Uri;
$uri1 = new Uri('HTTP://EXAMPLE.COM/Path?A=1&B=2');
$uri2 = new Uri('http://example.com/path?b=2&a=1');
echo (string) $uri1->withScheme('http')->withPath(strtolower($uri1->getPath()));
echo (string) $uri2->withScheme('http')->withPath(strtolower($uri2->getPath()));
http://example.com/path?a=1&b=2 http://example.com/path?a=1&b=2
Пояснение: фактически требуется нормализация схемы, пути и сортировка параметров. В реальном коде лучше использовать библиотеку для глубокого сравнения.