かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

PHP PDO 直近にINSERTされたデータのIDを取得したい

mysql_connect()MySQL接続していた時でいう所のmysql_insert_id()の様に直近にINSERTされたデータのIDをPDOで取得する方法。

lastInsertID()を使う。
http://php.net/manual/ja/pdo.lastinsertid.php

public string PDO::lastInsertId ([ string $name = NULL ] )
最後に挿入された行の ID、 あるいはシーケンスオブジェクトから次の値をを返します。 これは、構成しているドライバに依存します。例えば PDO_PGSQL の場合、name パラメータにシーケンスオブジェクト名を指定する必要があります。

注意: このメソッドは、異なる PDO ドライバ間で意味のあるもしくは 一貫性のある結果を返さないかも知れません。 構成しているデータベースが自動インクリメントフィールド、 もしくはシーケンスの概念をサポートしていないかも知れないためです。

 
データベースによっては上手く動作しないっぽですが、次のような感じで取得することができました。

<?php
try {
  $pdo = new PDO(
    'mysql:host=' . HOST_NAME . ';dbname=' . DB_NAME . ';charset=utf8',
    DB_USER,
    DB_PASS,
    array(
      // カラム型に合わない値がINSERTされようとしたときSQLエラーとする
      PDO::MYSQL_ATTR_INIT_COMMAND => "SET SESSION sql_mode='TRADITIONAL'",
      // SQLエラー発生時にPDOExceptionをスローさせる
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    )
  );
  
  // idは AUTO_INCREMENT 
  $sql = 'INSERT INTO ' . TABLE_NAME . '(id, name, value) VALUES (null, :name, :value)';
  $stmt = $pdo->prepare($sql);

  // トランザクション開始
  $pdo->beginTransaction();
  try {
    $name = '暁型駆逐艦 響';
    $value = 2;

    $stmt->bindValue(':name', $name, PDO::PARAM_STR);
    $stmt->bindValue(':value', $value, PDO::PARAM_INT);
    $executed = $stmt->execute();

    // INSERTされたデータのIDを取得
    $id = $pdo->lastInsertId('id');

    // トランザクション完了
    $pdo->commit();
  } catch (Exception $e) {
    // トランザクション取り消し
    $pdo->rollBack();
    throw $e;
  }
} catch (PDOException $e) {
  exit($e->getMessage());
}

トランザクションとか正確に理解できていないのですが、$pdo->commit();の後にlastInsertId()を書くと常に0となってしまい、うまくidが取得できませんでした。
直近にINSERTされたデータのIDが欲しい場合はトランザクションを完了させる前に$pdo->lastInsertId();を記述しなければダメっぽい。


[参考]

気づけばプロ並みPHP 改訂版--ゼロから作れる人になる!

気づけばプロ並みPHP 改訂版--ゼロから作れる人になる!

  • 作者:谷藤 賢一
  • 発売日: 2017/02/18
  • メディア: 単行本(ソフトカバー)