web-dev-qa-db-ja.com

なぜdbDelta()はMysqlErrorsをキャッチしないのですか?

私が見ることができるものから、dbDelta()は操作中に発生するデータベースエラーを抑制するように設計されています。一般的に言って、これは当てはまるようですが、New Relicはまだ関数からMysqlErrorsを報告しています。正確なエラーメッセージは次の形式です。

MysqlError: Table 'xxx.wp_yyy_posts' doesn't exist

/wp-admin/includes/upgrade.phpdbDelta()から、次のようになります。

// Fetch the table column structure from the database
$suppress = $wpdb->suppress_errors();
$tablefields = $wpdb->get_results("DESCRIBE {$table};");
$wpdb->suppress_errors( $suppress );

suppress_errors()が仕事をしていて、エラーメッセージが画面に表示されないようにしているようです。 ただし、New Relicのインストールで示されているように、これらのエラーは実際には処理されていないようです。

当然のことながら、実際のエラー率を追跡するためにNew Relicツールを正確に使用し、それらをNew Relicのレポート作成ツールに関連付けることができるように、プロダクションアプリケーションで考えられるすべてのエラーの原因を排除したいと思います。

dbDelta()がこのエラーを処理しない説得力のある理由はありますか?考えられる唯一の理由は、これが開発を容易にするための意図的な設計上の決定であるということです。そしてバグ修正。 dbDelta()がエラーを完全に抑制する場合、開発者が問題を突き止めるのは難しいかもしれません。もちろん、この自動的なエラー抑制を行うべきかどうかを指定するために新しいパラメータ/オプションを導入することもできます(これはMysqlErrorを捕捉することを非常に簡単にします)。

install_blog()を呼び出すたびにこのエラーが発生するという私たちの場合、これはちょっとした問題になります。大規模なマルチサイトインストールを実行しているため、新しいブログを作成するたびにエラーが発生します。

3
rinogo

@Charleston Software Associatesが述べたように、テーブルが存在しない場合はDESCRIBEクエリを実行しないでください。彼が指摘したように、最善の解決策は、まずエラーが発生しないようにすることです。

そのためには、wp-admin/includes/upgrade.phpに次のようにパッチを当てます。

DbDelta()から次の行を変更します。

  $tablefields = $wpdb->get_results("DESCRIBE {$table};”);

に:

    //Begin core hack - See http://wordpress.stackexchange.com/q/141971/10388
    $check_table = $wpdb->get_results("SHOW TABLES LIKE '".str_replace("_", "\_", $table)."';");
    if(!empty($check_table))
        $tablefields = $wpdb->get_results("DESCRIBE {$table};");
    else
        $tablefields = null;
    //End core hack

これは最もクリーンな解決策ではありませんが(特にコアハックであるため)、少なくとも私にとってはうまくいきます!おそらくそれは他の誰かを助けるでしょう。

更新:下記の私のコメントを参照してください。 (これは問題を完全に解決するわけではありませんが、正しい方向への一歩ですが)

1
rinogo

そのタイプのDBエラーは、DB_DEBUGが有効な場合にのみUIに表示されます。本番システムでは無効にする必要があります。 WPインストール用のwp-config.phpファイルにその設定があるはずです。

EZSQL_ERRORグローバルをリセットすることで、手動でエラーを「隠す」ように強制することができます。これは私の個人的なハックであり、おそらくdbDeltaを使用するための推奨またはベストプラクティスではありません。

/**
 * Update the data structures on new db versions.
 *
 * @global object $wpdb
 * @param type $sql
 * @param type $table_name
 * @return string
 */
function dbupdater($sql,$table_name) {
    global $wpdb;
    $retval = ( $wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name ) ? 'new' : 'updated';

    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    $were_showing_errors = $wpdb->show_errors;
    $wpdb->hide_errors();
    dbDelta($sql);
    global $EZSQL_ERROR;
    $EZSQL_ERROR=array();
    if ( $were_showing_errors ) {
        $wpdb->show_errors();
    }

    return $retval;
}
0
Lance Cleveland