Есть много сообщений о преобразовании относительно абсолютных путей в PHP. Я ищу конкретную реализацию за пределами этих должностей (надеюсь). Может ли кто-нибудь помочь мне в этой конкретной реализации?
У меня есть переменная PHP, содержащая разнообразные HTML, включая href
s и img
s, содержащие относительные URL-адреса. В основном (например) /en/discover
или /img/icons/facebook.png
Я хочу обработать эту переменную PHP таким образом, чтобы значения my href
s и img
s были преобразованы в http://mydomain.com/en/discover
и http://img.ruphp.com/php/facebook.png
Я считаю, что вопрос ниже охватывает решение для href
s. Как мы можем расширить это, чтобы также рассмотреть img
s?
Будет ли регулярное выражение в порядке? Или, поскольку мы имеем дело с большим количеством результатов, мы должны использовать DOMDocument?
После некоторых дальнейших исследований я наткнулся на эту статью Герда Риссельмана о том, как решить проблему отсутствия base href
решения для RSS-каналов. Его фрагмент действительно решает мой вопрос!
http://www.gerd-riesselmann.net/archives/2005/11/rss-doesnt-know-a-base-url
<?php function relToAbs($text, $base) { if (empty($base)) return $text; // base url needs trailing / if (substr($base, -1, 1) != "/") $base .= "/"; // Replace links $pattern = "/<a([^>]*) " . "href=\"[^http|ftp|https|mailto]([^\"]*)\"/"; $replace = "<a\${1} href=\"" . $base . "\${2}\""; $text = preg_replace($pattern, $replace, $text); // Replace images $pattern = "/<img([^>]*) " . "src=\"[^http|ftp|https]([^\"]*)\"/"; $replace = "<img\${1} src=\"" . $base . "\${2}\""; $text = preg_replace($pattern, $replace, $text); // Done return $text; } ?>
Спасибо, Герд! И спасибо, тенедикс, чтобы указать мне в сторону base href
!
Отличное решение. Однако в шаблоне есть небольшая опечатка. Как написано выше, он обрезает первый символ href или src. Вот образцы, которые работают по назначению:
// Replace links $pattern = "/<a([^>]*) " . "href=\"([^http|ftp|https|mailto][^\"]*)\"/";
а также
// Replace images $pattern = "/<img([^>]*) " . "src=\"([^http|ftp|https][^\"]*)\"/";
Начальная скобка вторых ссылок замены перемещается. Это приносит первый символ href или src, который не соответствует http | ftp | https в ссылках замены.
Я обнаружил, что когда href src и базовый url начали усложняться, принятое решение для ответа не сработало для меня.
например:
базовый url:
http://www.journalofadvertisingresearch.com/ArticleCenter/default.asp?ID=86411&Type=Article
href src:
/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
неверно возвращено:
/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
Я нашел функцию ниже, которая правильно возвращает URL-адрес. Я получил это от комментария здесь: http://php.net/manual/en/function.realpath.php от Исаака З. Шлютера.
Это верно вернулось:
http://www.journalofadvertisingresearch.com/ArticleCenter/LeftMenu.asp?Type=Article&FN=&ID=86411&Vol=&No=&Year=&Any=
function resolve_href ($base, $href) { // href="" ==> current url. if (!$href) { return $base; } // href="http://..." ==> href isn't relative $rel_parsed = parse_url($href); if (array_key_exists('scheme', $rel_parsed)) { return $href; } // add an extra character so that, if it ends in a /, we don't lose the last piece. $base_parsed = parse_url("$base "); // if it's just server.com and no path, then put a / there. if (!array_key_exists('path', $base_parsed)) { $base_parsed = parse_url("$base/ "); } // href="/ ==> throw away current path. if ($href{0} === "/") { $path = $href; } else { $path = dirname($base_parsed['path']) . "/$href"; } // bla/./bloo ==> bla/bloo $path = preg_replace('~/\./~', '/', $path); // resolve /../ // loop through all the parts, popping whenever there's a .., pushing otherwise. $parts = array(); foreach ( explode('/', preg_replace('~/+~', '/', $path)) as $part ) if ($part === "..") { array_pop($parts); } elseif ($part!="") { $parts[] = $part; } return ( (array_key_exists('scheme', $base_parsed)) ? $base_parsed['scheme'] . '://' . $base_parsed['host'] : "" ) . "/" . implode("/", $parts); }