Два URL идентичны? Игнорировать порядок параметров

У меня есть два URL-адреса, и я ищу лучший способ решить, идентичны ли они.

Пример:

$url1 = 'http://example.com/page.php?tab=items&msg=3&sort=title';
$url2 = 'http://example.com/page.php?tab=items&sort=title&msg=3';

В двух URL-адресах переключаются только параметры sort и msg, поэтому я считаю их равными. Однако я не могу просто сделать if ( $url1 == $url2 ) { … }

У меня есть список URL-адресов, и мне нужно найти дубликаты, поэтому код должен быть быстрым, поскольку он выполняется внутри цикла. (В качестве примечания: domain/page.php всегда будет одним и тем же, речь идет только о поиске URL-адресов по параметрам.)


person Philipp    schedule 27.12.2014    source источник
comment
Превращение параметров в ассоциативный массив, а затем использование array_diff может быть хорошим способом   -  person MDEV    schedule 27.12.2014
comment
Вам нужно будет объединить parse_url и parse_str. Либо сравнивая массивы параметров, либо сортируя их и собирая URL-адреса.   -  person mario    schedule 27.12.2014
comment
Разберите параметры с помощью parse_str, отсортируйте их с помощью ksort, а затем верните обратно. Тогда вы сможете их сравнить.   -  person Barmar    schedule 27.12.2014


Ответы (2)


Может вот так?

function compare_url($url1, $url2){
  return (parse_url($url1,PHP_URL_QUERY) == parse_url($url2,PHP_URL_QUERY));
}
person Lajos Veres    schedule 27.12.2014
comment
Это прекрасно :-) Я использую только parse_url() вместо preg_replace(). Очень хорошая идея сравнить массивы параметров! - person Philipp; 27.12.2014

Не так просто, как может показаться, узнать, идентичен ли URI или нет, особенно если учесть здесь параметр запроса.

Один из распространенных способов сделать это — использовать функцию, которая нормализует URL-адрес, а затем сравнивает нормализованные URI. :

$url1 = 'http://example.com/page.php?tab=items&msg=3&sort=title';
$url2 = 'http://example.com/page.php?tab=items&sort=title&msg=3';

var_dump(url_nornalize($url1) == url_nornalize($url2)); # bool(true)

В такую ​​функцию нормализации вы вкладываете свои требования. Прежде всего, URL-адрес должен быть нормализован в соответствии со спецификациями:

function url_nornalize($url, $separator = '&')
{
    // normalize according RFC 3986
    $url = new Net_URL2($url);
    $url->normalize();

И тогда вы можете позаботиться о дополнительных шагах нормализации, например, отсортировав подчасти запроса:

    // normalize query if applicable
    $query = $url->getQuery();
    if (false !== $query) {
        $params = explode($separator, $query);
        sort($params);
        $query = implode($separator, $params);
        $url->setQuery($query);
    }

Могут быть предусмотрены дополнительные шаги, такие как удаление параметров по умолчанию или недопустимых, дублирование параметров и т. д.

Наконец, возвращается строка нормализованного URL.

    return (string) $url;
}

Использование массива/хеш-карты для параметров тоже неплохо, я просто хотел показать альтернативный подход. Полный пример:

<?php
/**
 * http://stackoverflow.com/questions/27667182/are-two-urls-identical-ignore-the-param-order
 */

require_once 'Net/URL2.php';

function url_nornalize($url, $separator = '&')
{
    // normalize according RFC 3986
    $url = new Net_URL2($url);
    $url->normalize();

    // normalize query if applicable
    $query = $url->getQuery();
    if (false !== $query) {
        $params = explode($separator, $query);
        // remove empty parameters
        $params = array_filter($params, 'strlen');
        // sort parameters
        sort($params);
        $query = implode($separator, $params);
        $url->setQuery($query);
    }

    return (string)$url;
}

$url1 = 'http://EXAMPLE.com/p%61ge.php?tab=items&&&msg=3&sort=title';
$url2 = 'http://example.com:80/page.php?tab=items&sort=title&msg=3';

var_dump(url_nornalize($url1) == url_nornalize($url2)); # bool(true)
person hakre    schedule 27.12.2014