Обычно задача возникает, когда мы исследуем скриптом html страничку, и нам нужно получить, используя её абсолютный адрес, адреса страниц на которые она ссылается. Для этого к текущему абсолютному адресу страницы, надо «добавлять» адреса других страниц. Эти адреса могут быть абсолютным или относительным, канонизированными и нет и т.д.
Возникает полдюжины ветвлений, которые нужно проанализировать. Функция вернет результирующий путь или false, если входные данные покажутся ей не верными.
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 |
function linkSumm($link, $base) { if (!preg_match('~^(http://[^/?#]+)?([^?#]*)?(\?[^#]*)?(#.*)?$~i', $link.'#', $matchesLink)) return false; //ссылка имеет вид абсолютной if (!empty($matchesLink[1])) return $link; if (!preg_match('~^(http://)?([^/?#]+)(/[^?#]*)?(\?[^#]*)?(#.*)?$~i', $base.'#', $matchesBase)) return false; if (empty($matchesLink[2])) { if (empty($matchesLink[3])) //ссылка имеет вид переходя к якорю return 'http://' . $matchesBase[2] . $matchesBase[3] . $matchesBase[4]; //та же стр, но новые параметры return 'http://'.$matchesBase[2].$matchesBase[3].$matchesLink[3]; } $pathLink = explode('/', $matchesLink[2]); if ($pathLink[0] == '') //если путь задан от корня сайта (начинается со слеша) return 'http://' . $matchesBase[2] . $matchesLink[2] . $matchesLink[3]; //отрабатываем относительные смещения /../, что даст нам канонизированный путь $pathBase = explode('/', preg_replace('~^/~', '', $matchesBase[3])); if (sizeOf($pathBase) > 0) array_pop($pathBase); foreach ($pathLink as $p) { if ($p == '.') { continue; } elseif ($p == '..') { if (sizeOf($pathBase) > 0) array_pop($pathBase); } else array_push($pathBase, $p); } //сборка ссылки return 'http://'.$matchesBase[2].'/'.implode('/', $pathBase).$matchesLink[3]; } |
Функция незаменима, если вы пишите «паучка». Сначала я написал какой то свой вариант этой функции. Но она не выполняла канонизации. Тогда я хорошо покопался в ру-нете и нашел этот готовый код. Автор обошелся без вызова функций realpath() и parse_url(). От меня — комменты и форматирование ;)