Pull to refresh

Comments 17

UFO just landed and posted this here
Не совсем понял вопроса. Видимо, скопировать )
Если вы о том, что у меня в топике код без отступов, то вот так хабр тег CODE отображает. Можно PRE сделать, но тогда через строчку будут идти пустые строки :(
Думаю лучше копировать напрямую с http://pyha.ru/forum/topic/181.0
А parse_url уже отменили?

Столько регулярных выражений и мусора, что просто жуть.
print_r(parse_url('site.ru/path'));
print_r(parse_url('user:password@site.ru/path'));

parse_url() сосет.
Вернее, он не совсем для этого случая.
Вообще-то parse_url работает правильно. Т.к. ваш пример некорректен. Особенно, если смотреть первый вариант - его можено поменять на "page.pl/path" и в итоге получим не то, что надо. Стоит добавить к примерам http:// и всё будет ок. Для того, чтобы определить - наличествует ли протокол, хватит одной регулярки. А если учетывать только http (как в функции), то вообще можно обойтись без регулярок.

parse_url может заменить большую часть кода данной функции. Остальную часть заменит realpath.
А куда этот "http://" добавлять? Прочитайте условие — на входе может быть абсолютный URI, абсолютный путь на сайте и относительный.
Этой регуляркой, видимо, производится извлечение всех возможных частей, а потом по их наличию определяется тип ссылки.
Тогда данный скрипт отрабатывает не в соответствии с поставленной задачей.

Скрипт по умолчанию полагает, что ссылки бывают только протокола http. Также, он полагает, что если URL не абсолютный, и первый символ - не '/', то значит это - домен.

С такой же наивностью может работать и предложенный мной вариант. Работать будет быстрее, а главное, код будет яснее.
> Также, он полагает, что если URL не абсолютный, и первый символ - не '/', то значит это - домен

под "этим" подразумевается первый фрагмент до / в $base. Равно как и обработка $link весьма неоднозначна.
Проверить на http в начале. Вырезать. Проверить на "/" в начале. Проверить на "?#" вначале. Например, вся ссылка - "?param". Пропустить, через parse_url, проверять наличие элементов, не забывая isSet().
Не уверен, что это будет принципиально лучше и быстрее.

realpath()? Вот у есть абсолютный базовый путь "/a/b" и относительный "c/../.././d/e". Приведите пример с realpath() для вычисления.
Насколько знаю, он вычисляет от текущего пути и требует наличия файла.

Может еще какие-то причины были. Можно спросить у автора.
Нашел бы первым вариант с parse_url + relapath дал бы ссылку на него :)
Насчёт realpath действительно ошибся. А так, мой вариант кода - ниже.
использовал данную функцию в своём поисковом пауке, полезная вещь
легко можно клеит ссылки из страниц с
Короче вот, наваял (хабраавторы, сделайте какой-нибудь вменяемый способ постить код). Данная функция использует только одну регулярку (и то, только в случае, если есть '/../'). Она также корректно обрабатывает все варианты URI (в отлиичие от вышеопубликованного кода):

relative/path
/root/path
?arguments&change&only
#anchor_change_only
user:pass@host/path
http://host

function uri2url($link, $base) {
if (!strpos($base, '://')) {
$base = 'http://' . $base;
}
$base = parse_url($base);
unset($base['fragment']);

if (!strpos($link, '://') and strpos($link, '@')) {
$link = $base['scheme'] . '://' . $link;
}
$link = parse_url($link);

if (isset($link['host'])) {
if ($link['host']!=$base['host']) {
return false;
}
unset($base['path'], $base['query']);
} elseif (isset($link['path']) and $link['path'][0] != '/') {
if($base['path'][strlen($base['path'])-1]=='/') {
$link['path'] = $base['path'] . $link['path'];
} else {
$path = pathinfo($base['path']);
$link['path'] = $path['dirname'] . '/' . $link['path'];
}
}
if (isset($link['path']) or isset($link['query'])) {
unset($base['query']);
}
extract($link + $base);
str_replace('/./', '/', $path);
while (strpos($path, '/../') !== false) {
$path = preg_replace('~(/[^/]+)?/\.\./~', '/', $path);
}
return $scheme . '://'
. (isset($user) ? $user . (isset($pass) ? ':' . $pass : '') . '@' : '')
. $host . $path
. (isset($query) ? '?' . $query : '')
. (isset($fragment) ? '#' . $fragment : '');
}
Так как уж началась дискуссия, я, таки, протестировал оба варианта.
У вас на 3 строчки длинее :) и не сказать, что понятнее.
Время выполнения практически одинаковое (и по большому счету ничтожное)

Результаты:
uri2url('relative/path', 'http://site.com/x') - http://site.com\/relative/path появляется лишний "\".
uri2url('./../z', 'http://site.com/x') - http://site.com\/z - аналогично

Так же у вас остаются якоря, а в функции из моего поста нет. Вопрос спорный, конечно, но так как скорее всего ссылки будут использованы для запроса страниц, думаю uri2absolute ведет себя более правильно.

http://host - ваша ничего не вернула. uri2absolute() отработала как надо
user:pass@host/path - таких URL вообще быть не может (user будет рассматриваться, как протокол). Впрочем, ваша функции так же ничего и не вернула :)
Вы под какой версией php и на какой системе тестировали?
Спасибо! Выручил. А то я замучился свой велосипед писать. Сразу в сети ничего не нашел :(
Sign up to leave a comment.

Articles