【PHP】PDOのFETCH_CLASSを使って「モデル」っぽくDBを扱う方法

「フレームワークを使わないバニラなPHP」で開発する場合、DBから取得したデータをどう扱うか?

FETCH_ASSOC で連想配列として回すと楽に思えるが、「クラス(オブジェクト)」 に流し込むと、コードの見通しが良くなる。


1. フェッチモード(データの受け取り方)

PDOでデータを取得する際、fetch()fetchAll() の引数に指定する「モード」によって、返ってくるデータの形が変わる 。

モード戻り値の型特徴・使いどころ
PDO::FETCH_ASSOC連想配列$row['name'] でアクセス。最も手軽で軽量。
PDO::FETCH_OBJ匿名オブジェクト$row->name でアクセス。stdClass に入る。
PDO::FETCH_CLASS指定したクラス$row->name でアクセス。自作メソッドが使える最強のモード。

2. PDOを使った基本の「型」

DB接続からデータ取得までの基本ステップは以下の通りです。

PHP

// 1. 接続
$dsn = 'mysql:host=localhost;dbname=your_db;charset=utf8mb4';
$pdo = new PDO($dsn, 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // デフォルト設定
]);

// 2. 準備
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");

// 3. 実行
$stmt->execute(['id' => 1]);

// 4. 取得(ここでモードを切り替える)
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
$user = $stmt->fetch();

3. 「データ特有の処理」をモデルに持たせる

ただの配列ではなく、クラス(モデル)を使う最大のメリットは、「そのデータに関するルール」をクラス内に閉じ込められることである。

実装例:Userクラス

PHP

class User {
    public $id;
    public $first_name;
    public $last_name;
    public $role;

    /**
     * フルネームを生成する(加工ロジック)
     */
    public function getFullName(): string {
        return "{$this->last_name} {$this->first_name}";
    }

    /**
     * 管理者かどうか判定する(判定ロジック)
     */
    public function isAdmin(): bool {
        return $this->role === 'admin';
    }
}

呼び出し側のコード

PHP

// FETCH_CLASSで取得していれば、メソッドがそのまま使える
if ($user) {
    echo "こんにちは、" . $user->getFullName() . "さん";
    
    if ($user->isAdmin()) {
        echo "管理者用パネルを表示します。";
    }
}

4. なぜ「配列」より「クラス」なのか?

もし配列(FETCH_ASSOC)を使っていると、フルネームを表示したい箇所すべてで $user['last_name'] . $user['first_name'] と書くハメになる。

クラス(モデル)化のメリット:

  • 保守性: 「名前の間にスペースを入れたい」となった時、クラスのメソッドを1箇所直すだけで全画面に適用される。
  • 可読性: $user->isAdmin() と書く方が、条件式を直接書くより「何をしたいか」が明白。
  • 補完: 優秀なエディタ(VSCodeなど)なら、プロパティやメソッドを補完してくれる。

まとめ:脱・連想配列のススメ

最初は「クラスを作るのが面倒」と感じるかもしれないが、規模が大きくなるほどこの数行のクラス定義が助けになる。

PDOの FETCH_CLASS を使いこなして、スッキリとしたオブジェクト指向なコードを目指すのがよいだろう。