PHP Note 》
2つのパス間の相対パスを得る
created: 2003-03-21 | modified: 2003-03-21
相対パスが必要な時って結構あると思うけど、PHPには絶対パス名を返す realpath はあるけどこの逆は無い。どうすれば相対パス得られるか考えてみました。
相対パスは、基準となるパスと対象のパスの位置関係だから、どっちも絶対パスと考えて文字列として順番に比較していけば出来そうだな、と思ったわけです。
<?php
/*
string relativePath ( $base, $target [, $option ] )
--------------------------------------------------------
$base から見た $target の相対パス文字列を返します。
--------------------------------------------------------
・引数 $base と $target は、同じディレクトリ名から始まる
パスを示す文字列でなければなりません。
・引数に相対パスを指定した場合の戻り値は責任持てません。
・$option には、$base と $target が同じディレクトリか
または、$target が下位だった場合、初めに "./" を付加する
かどうかを設定します。デフォルトでは付加されます。
・単純にパスを文字列として比較処理しているだけでファイルの
有無を確かめてるわけではありません。
*/
function relative_url ( $base, $target, $option = true )
{
// 戻り値($url)を $option に基づいて初期化
$url = ($option) ? './': '';
// 構成要素を '/' で分解
$base = explode('/', $base);
$target = explode('/', $target);
// 要素をはじめから順番に比較し同じ要素は排除
do {
$f = array_shift($base);
$t = array_shift($target);
} while ($f == $t);
// 要素をひとつ捨てすぎたので配列に戻す
array_unshift($base, $b);
array_unshift($target, $t);
// 残りの要素数を数える
$bcount = count($base);
$tcount = count($target);
// ひとつずつしか残ってないので同じディレクトリだ!
if ($bcount == 1 && $tcount == 1) {
// ならばファイル名だけを $url に格納
$url .= array_pop($target);
} else {
// 上位へ走査が必要な分 '../' を出力
if($bcount > 1) {
$url = str_repeat('../', $bcount - 1);
}
// $target のパスを '/' で連結して $url に格納
$url .= implode('/', $target);
}
// 出来上がったところで出力
return $url;
}
?>
配列に入れたり出したり、もっとスマートに書けそうな気もしますが、今のスキルではこれが限界です。
実際これ使う際は、ルートディレクトリからの絶対パスか、DocumentRoot(ベースディレクトリ)からの絶対パスを用いると整合性を取りやすいと思います。
もし相対パスを引数にしたいなら、あらかじめ realpath で絶対パスに直せばいいですね。
PHP Note 》
