2012年5月17日木曜日

[PHP] 配列の前のキー、次のキーを取得する

配列で特定のキーの前のキー、もしくは次のキーを取得したい時がある。
キーさえわかってしまえば、前の値や次の値も簡単に取れる。
array_keysを使ってキーだけの配列を作り、
更にキーだけの配列に第二引数つきのarray_keysを使って取得するのもありだとは思うが、
配列が大きい時に、array_keysで更に配列を作ると効率が悪い。
そういう時は素直にforeachで調べるのがベター。

//link・・・http://mio-koduki.blogspot.jp/2012/05/php.html
//第一引数・・・調べたい配列
//第二引数・・・基準となるキー
//返り値・・・調べたい配列の、基準となるキーの前のキーが返る。なければfalse
function prev_key($array,$key)
{
    $tmp=false;
    foreach($array as $k=>$v)
    {
        if($k==$key)
        {
            return $tmp;
        }
        $tmp=$k;
    }
    return false;
}

//link・・・http://mio-koduki.blogspot.jp/2012/05/php.html
//第一引数・・・調べたい配列
//第二引数・・・基準となるキー
//返り値・・・調べたい配列の、基準となるキーの次のキーが返る。なければfalse
function next_key($array,$key)
{
    $tmp=false;
    foreach($array as $k=>$v)
    {
        if($k==$key)
        {
            $tmp=$k;
        }
        elseif($tmp!==false)
        {
            return $k;
        }
    }
    return false;
}

記述的にはarray_keysなどを使ったほうがスマートに見えるが、
処理速度やメモリなどを考慮するとやはりforeachで処理するのがベターだと思う。

2012年5月9日水曜日

[PHP] http_build_urlを実装する

PECLにhttp_build_urlというURLを組み立ててくれる便利な関数があるが、
レンタルサーバや、相手のサーバの都合などでPECLを導入できないことがある。
となると、自分で実装するしかない。
http_build_urlの使い方はPHPマニュアルに乗ってるので参考にするといいかもしれない。

//link・・・http://mio-koduki.blogspot.jp/2012/05/php-httpbuildurl.html

//PECLのhttp_build_urlがある可能性があるためチェックする
if(!function_exists('http_build_url'))
{
    //フラグの定数を設定
    define('HTTP_URL_REPLACE',1);
    define('HTTP_URL_JOIN_PATH',2);
    define('HTTP_URL_JOIN_QUERY',4);
    define('HTTP_URL_STRIP_USER',8);
    define('HTTP_URL_STRIP_PASS',16);
    define('HTTP_URL_STRIP_AUTH',24);
    define('HTTP_URL_STRIP_PORT',32);
    define('HTTP_URL_STRIP_PATH',64);
    define('HTTP_URL_STRIP_QUERY',128);
    define('HTTP_URL_STRIP_FRAGMENT',256);
    define('HTTP_URL_STRIP_ALL',504);

    function http_build_url($url,$parts=array(),$flags=HTTP_URL_REPLACE,&$new_url=array())
    {
        //置き換えるキー
        $key=array('user','pass','port','path','query','fragment');
        //urlをパースする
        $new_url=parse_url($url);
        //スキーマとホストが設定されていれば置き換える
        if(isset($parts['scheme']))
        {
            $new_url['scheme']=$parts['scheme'];
        }
        if(isset($parts['host']))
        {
            $new_url['host']=$parts['host'];
        }
        //フラグにHTTP_URL_REPLACEがあれば置き換える
        if($flags&HTTP_URL_REPLACE)
        {
            foreach($key as $v)
            {
                if(isset($parts[$v]))
                {
                    $new_url[$v]=$parts[$v];
                }
            }
        }
        else
        {
            //フラグにHTTP_URL_JOIN_PATHがあり新しいパスがあれば新しいパスをつなげる
            if(isset($parts['path'])&&$flags&HTTP_URL_JOIN_PATH)
            {
                if(isset($new_url['path']))
                {
                    $new_url['path']=rtrim(preg_replace('#'.preg_quote(basename($new_url['path']),'#').'$#','',$new_url['path']),'/').'/'.ltrim($parts['path'],'/');
                }
                else
                {
                    $new_url['path']=$parts['path'];
                }
            }
            //フラグにHTTP_URL_JOIN_QUERYがあり新しいクエリがあれば新しいクエリをつなげる
            if(isset($parts['query'])&&$flags&HTTP_URL_JOIN_QUERY)
            {
                if(isset($new_url['query']))
                {
                    $new_url['query'].='&'.$parts['query'];
                }
                else
                {
                    $new_url['query']=$parts['query'];
                }
            }
        }
        //ストリップフラグの判定をし、設定されていれば消す
        foreach($key as $v)
        {
            if($flags&constant('HTTP_URL_STRIP_'.strtoupper($v)))
            {
                unset($new_url[$v]);
            }
        }
        //パーツを繋げて返す
        return (isset($new_url['scheme'])?$new_url['scheme'].'://':'').(isset($new_url['user'])?$new_url['user'].(isset($new_url['pass'])?':'.$new_url['pass']:'').'@':'').(isset($new_url['host'])?$new_url['host']:'').(isset($new_url['port'])?':'.$new_url['port']:'').(isset($new_url['path'])?$new_url['path']:'').(isset($new_url['query'])?'?'.$new_url['query']:'').(isset($new_url['fragment'])?'#'.$new_url['fragment']:'');
    }
}

という感じになる。
しょっちゅう使うものではないにしても、
たまにあると便利な時がある。

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