m6uのエンジニアっぽい日記

PHP利用開発やFuelPHP利用開発、PostgreSQL利用開発、Androidアプリ開発、CentOS7サーバー構築など、テクニカルでエンジニアっぽい内容の日記

PHP: PDO経由でMySQL接続するときのあれこれ

 数週間後(?)の自分に向けてのメモ(?)

基本形

 公式ドキュメント「PHP: PDO::__construct」にある方法。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策

 アレンジして、DSNに文字エンコーディング指定を加える。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策+エラートラップ強化

 さらにアレンジして、DB接続時以降の処理でエラー派生した時にも例外処理できるように強化する。
 公式ドキュメントにある方法「PHP: エラーおよびエラー処理」を参考に。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';

    try {
        $dbh = new PDO($dsn, $user, $password);
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);  // エラー発生時に例外スロー
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

基本形+UTF8トラブル対策+エラートラップ強化(別な書き方)

 もしくは、接続時にもう設定してしまう方法。 これは知らなかったなぁ。

<?php
    /* ドライバ呼び出しを使用して MySQL データベースに接続する */
    $dsn = 'mysql:dbname=testdb;host=127.0.0.1;charset=utf8';
    $user = 'dbuser';
    $password = 'dbpass';
    $options = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION  // エラー発生時に例外スロー
    );

    try {
        $dbh = new PDO($dsn, $user, $password, $options);
    } catch (PDOException $e) {
        echo 'Connection failed: ' . $e->getMessage();
    }
?>

あわせて読みたい

 PHP: 文字セットでは、PHPからMySQLに接続する際の文字セットにまつわる話がまとまっています。
 PDOを使うか、mysqliを使うかで、やり方も変わってくるそうで。

FuelPHP:Fieldsetでチェックボックスを扱う時の話

 ハマったのでメモ。
 9ensan作ViewFormパッケージを使っていて、はじめてadd_checkbox()を使ったら、これで半日ハマってしまった。 また同じことを繰り返しそうな気がするのでまとめます。

チェックボックスを複数個使うフォームに改造したのです→validationが通らなくなり
$fieldset = ViewForm\Fieldset::forge();
...
$this->arr_nooutput_r = array();
for ($i = 5; $i >= 1; $i--) {
    $this->arr_nooutput_r += array('r_'.$i => 'Rランク'.$i);
}
$fieldset->add_checkbox('no_output_r', 'Rランク出力抑止', $this->arr_nooutput_r);

…なんてコードを書いてました。 そしたら、「allow_empty_in_array」のルールに引っかかってバリデーションが通らなくなってしまったのです。

add_rule()してみても無駄でした
$fieldset = ViewForm\Fieldset::forge();
...
$this->arr_nooutput_r = array();
for ($i = 5; $i >= 1; $i--) {
    $this->arr_nooutput_r += array('r_'.$i => 'Rランク'.$i);
}
$fieldset->add_checkbox('no_output_r', 'Rランク出力抑止', $this->arr_nooutput_r)->add_rule('allow_empty_in_array', array_keys($this->arr_nooutput_r));

…としても同じです。 バリデーションが通らない。

もしかして連想配列で渡さず、配列で渡すものなのかな?→正解
$fieldset = ViewForm\Fieldset::forge();
...
$this->arr_nooutput_r = array();
for ($i = 5; $i >= 1; $i--) {
    array_push($this->arr_nooutput_r, 'Rランク'.$i);
}
$fieldset->add_checkbox('no_output_r', 'Rランク出力抑止', $this->arr_nooutput_r);

…としたところ、ウソだったみたいにバリデーションが通るようになりました。

生成されるinput要素を見ると、value属性はゼロ始まりの数字で、name属性は配列表記になってました

例えば

<input type="checkbox" value="0" id="form_no_output_r_0" name="no_output_r[0]" checked="checked" /><label for="form_no_output_r_0">Rランク5</label>

 こんな感じのhtml出力で、value属性を任意のものにしたいがために当初連想配列で渡したところ、おかしくなってしまったようです。
 これって、ViewFormパッケージ固有の話じゃなくて、ふつうにFieldsetクラスでadd()するときでも同じことなんじゃないかと。
 配列で渡そう。