basics.php – stripslashes_deep($value) (CakePHP解析 #10)

今回はdispatcher.phpで呼び出されているstripslashes_deep関数を解析します。

この関数はPHPのmagic_quotes_gpcがonの場合でも問題なく動作させるために使用されています。

if (ini_get('magic_quotes_gpc') == 1) {
    if (!empty($_POST)) {
        $params['form'] = stripslashes_deep($_POST);
    }
} else {
    $params['form'] = $_POST;
}

ここで、magic_quotes_gpcがonの場合に、裏でどんな処理が行われるのかをおさらいしておきます。

マニュアルによると

オンの場合、全ての’ (シングルクオート), ” (ダブルクオート), (バックスラッシュ)および

NULL 文字がバックスラッシュで自動的にエスケープされます。 これは、addslashes() の機能と同じです。

つまり、「Is your name O’reilly?」は、「Is your name O’reilly?」に自動的に変換されるわけです。

この変換処理はHTTPリクエストデータ(GET, POST, そして COOKIE)に対して行われます。

そして、この変換されてしまったデータを元に戻すために使用されるのがstripslashes_deep()関数です。

この関数は「cake/basics.php」内に定義されています。

function stripslashes_deep($value) {
    if (is_array($value)) {
        $return = array_map('stripslashes_deep', $value);
        return $return;
    } else {
        $return = stripslashes($value);
        return $return ;
    }
}

引数が配列で無い場合と、配列の場合で処理が分かれています。

まずは配列で無い場合ですが、stripslashes関数で変換した値を返して終了しています。

stripslashes関数はmagic_quotes_gpcが行う変換処理の反対の変換を、つまり

「Is your name O’reilly?」であれば、「Is your name O’reilly?」に変換します。

次は配列の場合の処理を見てみます。

まずarray_mapですが、これは第一引数で指定されている関数を、第二引数の配列の各値を引数にして呼び出す関数です。

ここでポイントになるのはarray_map内でstripslashes_deep関数を、つまり自分自身を関数内で呼び出している点です。

これは再帰関数と呼ばれるものになりますが、初めはなぜ「stripslashes」でなく「stripslashes_deep」を呼び出す必要があるのか疑問でした。

ただし、よくよく考えてみると配列の中身も配列、更にその中身も配列の可能性が…と考えると「なるほど再帰関数ってこういう

使い方をするのか」と感心してしまいました。

この関数を作った人が関数名に「_deep」と付けたのもうなづけます。

再帰関数を理解するのにうってつけのお手本ではないでしょうか。

DB日付値を任意のフォーマットで取得するコンポーネント(CakePHP修行 #10)

カレンダー・スケジュールに関するアプリを作っている関係上、どうしても日付に関する処理が多くなってしまいます。

DBに保存した日付値を任意のフォーマットに変換してくれるコンポーネントやヘルパーがデフォルトで用意されていないか探してみたのですが見つからない…。

多分、Timeヘルパーあたりにあると思うのですが、ヘルパーだとController内で使用することが出来ないので「DatetimeComponent」なるコンポーネントを自作してみました。

componentsフォルダにdatetime.phpファイルを作成し、下記のソースをコピペ。

・app/controllers/components/datetime.php

controller =& $controller;
    }

    function toFormat($elem, $format){
        //2008-02-27 00:00:00
        $set_year = substr($elem, 0, 4);    //年
        $set_month = substr($elem, 5, 2);    //月
        $set_day = substr($elem, 8, 2);        //日
        $set_hour = substr($elem, 11, 2);    //時
        $set_minute = substr($elem, 14, 2);    //分
        $set_second = substr($elem, 17, 2);    //秒

        return date($format, mktime($set_hour, $set_minute, $set_second, $set_month, $set_day, $set_year));
    }
}
?>

フォーマットの指定はPHPの標準関数であるDate関数と同じ形式です。

↓こんな感じで使用します。

$yyyy_m_d = $this->Datetime->toFormat($this->data['Schedule']['start'],'Y/n/j');

dispatcher.php – $this->parseParams($url) (CakePHP解析 #9)

今回は$Route->parseから戻ってparseParamsメソッドの解析をします。

以前解析したように$Route->parse(‘users/login/aaaa/bbbb/cccc/dddd?a=A&b=B’)の戻り値は

下記のような配列になります。

Array
(
    [pass] => Array
    (
        [0] => aaaa
        [1] => bbbb
        [2] => cccc
        [3] => dddd
    )
    [controller] => users
    [action] => login
)

この結果を$params変数が受け取っているわけですが、この$params変数は「$this->data」を保持する非常に重要な変数です。

下記のようにその後の処理でform値やurl値を取り込んでいます。

if (ini_get('magic_quotes_gpc') == 1) {
    if (!empty($_POST)) {
        $params['form'] = stripslashes_deep($_POST);
    }
} else {
    $params['form'] = $_POST;
}

次回はこの処理の中で使用されている「stripslashes_deep」関数を解析します。