PHPを使用してMySQLデータベースを接続および操作する場合、 MySQLI拡張機能はMySQLI :: Query 、 MySQLI :: PREPAREなどのリッチな方法を提供してSQLを実行します。ただし、実際の開発では、SQLが成功するかどうかに注意を払うことに加えて、実行プロセスを取得する必要がある場合があります。これらの警告はSQLの実行に失敗しない可能性がありますが、潜在的な問題を隠します。
PHPのmysqli :: get_warningsメソッドは、接続内の最後の操作によって生成されるすべての警告を取得できます。ただし、その使用はしばしば断片化されており、モジュールに包むことができれば、プロジェクトで簡単に再利用してコードをきれいに保つことができます。
この記事では、mysqli :: get_warningsを再利用可能なMySQL警告キャプチャモジュールにカプセル化する方法について説明します。
mysqli :: get_warnings()メソッドは、すべての警告情報にアクセスできるmysqli_warningオブジェクトのリンクリストへの参照を返します。各mysqli_warningオブジェクトには、次の情報が含まれています。
メッセージ:警告メッセージ
SQLSTATE :SQLSTATEエラーコード
errno :mysqlエラーコード
私たちの目標は、次のことができるWarningCollectorクラスを実装することです。
mysqliインスタンスにバインドします。
SQLステートメントを実行し、警告情報を自動的に収集します。
警告情報をフォーマットし、ログに返します。
次の操作に影響を与えるために残っている警告情報を避けるための警告クリーニング方法を提供します。
以下は完全な実装コードです。
<?php
class WarningCollector
{
private mysqli $conn;
private array $warnings = [];
public function __construct(mysqli $connection)
{
$this->conn = $connection;
}
public function execute(string $sql): bool|mysqli_result
{
$result = $this->conn->query($sql);
$this->collectWarnings();
return $result;
}
private function collectWarnings(): void
{
$this->warnings = []; // 古いデータをクリアします
$warning = $this->conn->get_warnings();
while ($warning) {
$this->warnings[] = [
'errno' => $warning->errno,
'sqlstate' => $warning->sqlstate,
'message' => $warning->message,
];
$warning = $warning->next();
}
}
public function getWarnings(): array
{
return $this->warnings;
}
public function hasWarnings(): bool
{
return !empty($this->warnings);
}
public function logWarnings(string $logPath = '/tmp/mysql_warnings.log'): void
{
if ($this->hasWarnings()) {
foreach ($this->warnings as $w) {
$entry = sprintf(
"[%s] MySQL Warning - Errno: %d, SQLSTATE: %s, Message: %s\n",
date('Y-m-d H:i:s'),
$w['errno'],
$w['sqlstate'],
$w['message']
);
file_put_contents($logPath, $entry, FILE_APPEND);
}
}
}
}
このモジュールを使用することは非常に簡単です。 SQLを実行する前に、接続をカプセル化するために使用するだけです。
<?php
$mysqli = new mysqli('localhost', 'user', 'pass', 'database');
$collector = new WarningCollector($mysqli);
// 埋め込む SQL
$sql = "INSERT INTO demo (name) VALUES ('duplicate-key')";
$collector->execute($sql);
// 警告を確認してください
if ($collector->hasWarnings()) {
$collector->logWarnings();
print_r($collector->getWarnings());
}
このカプセル化は、プロジェクトの次のカテゴリで特に役立ちます。
データ移行スクリプト:警告は、フィールドの切り捨てまたはタイプの不一致を明らかにする可能性があります。
バッチインポートツール:大規模なデータのバッチを挿入すると、制約関連の警告が簡単にトリガーされます。
データ品質の監視:後の分析のために、ログシステムを介した警告の集中コレクション。
Laravel、Symfonyなどのフレームワークを使用する場合、依存関係のインジェクションのためのこのアイデアに基づいて、それらをミドルウェアまたはサービスクラスにカプセル化することもできます。
mysqli :: get_warnings()は、最後の操作によって生成される警告のみを取得できますので、各SQL実行後すぐに電話をかけてください。
準備されたステートメントを使用している場合は、警告を受ける前に実行することを確認することをお勧めします。
MySQLバージョンが異なると、警告に対するサポートのレベルがわずかに異なり、開発および生産環境バージョンが一貫していることをお勧めします。
mysqli :: get_warningsをモジュールにカプセル化することにより、SQLの警告をより簡単にキャプチャして処理するだけでなく、システムの保守性と堅牢性の向上にも役立ちます。ログチャネルのサポートの追加、警告レベルフィルタリングなど、プロジェクト構造に応じてさらに拡張できます。
完全なプロジェクトの例については、次のことを参照してください。
https://gitbox.net/example/mysql-warning-collector