ZendFramework1でMySQLのエラーコードを取得

ZendFramework1でMySQL等のDBを利用する場合、エラーコードを判別して処理をしたい場合があります。

try {
       $db->insert("db_table", $bind);
       echo "(登録完了)";
} catch (Zend_Exception $e) {
       echo $e->getCode();
       echo $e->getMessage();
}

普通は、こんな感じですね。
ただし、困ったことにここで取れるエラーコードは「23000」など、大まかなエラーコードで
いろいろなエラーで結構重複しています。


https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
厳密には上記のMySQLエラーコード表にあるSQLSTATEが返ってきます。
そちらではなく、Errorコードの方が欲しい場合にどうするかです。
getMessage()で取れるStringをパースしてもいいのですが、面倒ですし不確実です。


Zend_Exception $e の中身をZend_Debug::dump($e)で覗いてみるとこんな感じです。

object(Zend_Db_Statement_Exception)#87 (8) {
  ["_previous":"Zend_Exception":private] => NULL
  ["message":protected] => string(111) "SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '123456739' for key 'uniq_key'"
  ["string":"Exception":private] => string(0) ""
  ["code":protected] => int(23000)
  ["file":protected] => string(69) "/usr/local/zend/share/ZendFramework/library/Zend/Db/Statement/Pdo.php"
  ["line":protected] => int(234)
  ["trace":"Exception":private] => array(12) {
  (途中略)
    ["previous":"Exception":private] => NULL
    ["errorInfo"] => array(3) {
      [0] => string(5) "23000"
      [1] => int(1062)
      [2] => string(57) "Duplicate entry '123456789' for key 'uniq_key'"
    }
  }
}

ちゃんと、最後のerrorInfoで欲しいエラーコード「1062」が入っていることが判ります。
しかし、これを取得する関数はありません。どうすれば・・・ということで試行錯誤してみた結果、
$e->getChainedException()->errorInfo[1] で取れます。
getChainedException()で、下位情報のPDOExceptionが取得でき、そこからerrorInfoを取得します。
Zend_Db_Statement_Exceptionからは直接取得できません。(たぶんprivateなので)
ですので、おそらくPDO(MySQL)に依存した方法です。他のDB等でどうなるかはしりません。


なぜこうなるのか・・・は抽象化した結果でしょうが、気にしないことにします。
正式な取得方法があるのかもしれませんが、MySQL以外使いませんし動けばいいのです!(ダメ思想)


修正したコードはこんな感じでしょうか。

try {
       $db->insert("db_table", $bind);
       echo "(登録完了)";
} catch (Zend_Exception $e) {
       if($e->getChainedException()->errorInfo[1] == 1062) {
            echo "(ERR:重複登録)";
       }
}