2012年2月21日火曜日

[PHP] 相対URLから絶対URLを作る

たまにURLの相対パスから絶対パスを取りたい時がある。
PHPのデフォルトの関数にありそうだけど実はなかったりする。
せっかくなので自作してみる。

ちなみにis_absolute関数は絶対パスかどうかを調べる関数で、
以前作成したものを使用。

対象はPHP5.2以上

//link・・・http://mio-koduki.blogspot.com/2012/02/php-urlurl.html
//第一引数・・・相対パス
//第二引数・・・基準のパス
//返り値・・・成功したら絶対パスの文字列を、失敗したらfalseを返す
function get_absolute_url($path,$base)
{
    //パスがURLの形式でない場合はfalseを返す
    if(($ppath=parse_url($path))===false)
    {
        return false;
    }

    //基準のパスがURLの形式でない、または絶対パスでない場合はfalseを返す
    if(($pbase=parse_url($base))===false||!is_absolute($base))
    {
        return false;
    }

    //パスが初めから絶対パスの場合は自身を返す
    if(is_absolute($path))
    {
        return $path;
    }
    //絶対パスの形式でないのにスキームがある場合はfalseを返す
    elseif(isset($ppath['scheme']))
    {
        return false;
    }
    //パスが空文字だった場合は現在のパスを返す
    elseif($path=='')
    {
        return is_absolute($base)?$base:false;
    }

 //パスがパラメータ、フラグメントのみの場合は基準のパスのパラメータを置き換えて返す
 if(strpos($path,'?')===0)
 {
  $absolute_path=preg_replace('#\?'.(isset($pbase['query'])?preg_quote($pbase['query'],'#'):'').'(\#'.(isset($pbase['fragment'])?preg_quote($pbase['fragment'],'#'):'').')?$#','',$base).$path;
  return is_absolute($absolute_path)?$absolute_path:false;
 }
    //パスがフラグメントのみの場合は基準のパスのフラグメントを置き換えて返す
    if(strpos($path,'#')===0)
    {
        $absolute_path=preg_replace('#\#'.(isset($pbase['fragment'])?preg_quote($pbase['fragment'],'#'):'').'$#','',$base).$path;
        return is_absolute($absolute_path)?$absolute_path:false;
    }

    $absolute_path=$pbase['scheme'].'://'.$pbase['host'];
    $tmp_path=array();

    //パスがルートパスの場合はスキームとホストをつけて返す
    if(strpos($path,'/')===0)
    {
        $absolute_path.=$path;
        return is_absolute($absolute_path)?$absolute_path:false;
    }

    //基準のパスのパス部分を取得
    $base_path=isset($pbase['path'])?preg_replace('#^/#','',$pbase['path']):'';
    if($base_path!=''&&strpos($base_path,'/')!==false)
    {
        $tmp_path=explode('/',substr($base_path,0,substr($base_path,-1,1)=='/'?-1:strrpos($base_path,'/')));
    }

    //基準のパスのパス部分の階層をたどっていく
    $exploded_path=explode('/',$path);
    foreach($exploded_path as $v)
    {
        if(preg_match('#^\.+$#',$v))
        {
            if($v!='.')
            {
                $count=strlen($v)-1;
                array_splice($tmp_path,count($tmp_path)-$count,$count);
            }
            continue;
        }
        $tmp_path[]=$v;
    }

    //パスなどをつなげて絶対パスを返す
    $absolute_path.='/'.implode('/',$tmp_path);
    return is_absolute($absolute_path)?$absolute_path:false;
}

//link・・・http://mio-koduki.blogspot.com/2012/02/php.html
//第一引数・・・絶対パスかどうか調べたいパス
//返り値・・・絶対パスであればtrue、そうでなければfalse
function is_absolute($url)
{
    return
    ($purl=parse_url($url))!==false
    &&isset($purl['scheme'])
    &&isset($purl['host'])
    &&filter_var
    (
        $url,
        FILTER_VALIDATE_URL,
        FILTER_FLAG_PATH_REQUIRED,
    );
}

第一引数に調べたい相対パスと第二引数に基準となるパス(基本現在のパス)を渡せば
成功した際に絶対パスの文字列を、失敗した際にfalseを返す仕様になっている。

ポイントとなる関数
  • parse_url ・・・ URLを解釈し、その構成要素を返す

0 件のコメント:

コメントを投稿