データベース操作にPDOを使用する場合、 pdostatement :: fetchObjectは非常に便利な方法であり、クエリ結果をオブジェクトに直接マッピングできます。ただし、データベース内の整数( int )であったフィールドが文字列(文字列)に変換されるなど、タイプの不一致の問題に遭遇することがあります。この状況は、大量のデータを扱う場合、または厳密なタイプのデータ構造を必要とする場合、特に面倒です。
理由と解決策を見てみましょう。
pdostatement :: FetchObject自体は、データベースフィールドのタイプに基づいてPHPのタイプを自動的に推測しません。それは単にデータをオブジェクトプロパティに埋めるだけであるため、数値は文字列として処理されます。これは、PDOがデフォルトですべてのデータを文字列として返すためです。
例を見てみましょう:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT id, name FROM users');
$user = $stmt->fetchObject();
var_dump($user);
?>
出力は次のとおりです。
object(stdClass)#1 (2) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "John"
}
ご覧のとおり、 IDがデータベース内のINTタイプであっても、結果はPHPの文字列になります。
この問題を解決するためのいくつかの一般的な方法があります。
PDOには、 pdo :: attr_stringify_fetchesという設定があり、数字を文字列に自動的に変換するかどうかを制御できます。ただし、このオプションはFetch()シリーズ関数でのみ効果的であり、 FetchObjectに直接的な影響を与えないため、推奨されないことに注意する必要があります。
最も実用的な方法は、クラスを定義し、コンストラクターまたはマジックメソッド__setでタイプ変換を手動で実行することです。
例えば:
<?php
class User {
public int $id;
public string $name;
public function __construct() {
// ここでタイプ強制を実行できます
}
public function __set($name, $value) {
if ($name === 'id') {
$this->id = (int) $value;
} elseif ($name === 'name') {
$this->name = (string) $value;
}
}
}
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT id, name FROM users');
$user = $stmt->fetchObject(User::class);
var_dump($user);
?>
このようにして、データベースからデータを取得すると、タイプが正しいことを確認できます。
SQLステートメントでは、次のような必要なタイプに直接フィールドを強制します。
SELECT id + 0 AS id, name FROM users
このようにして、データベースが返されるとIDはすでに整数ですが、この方法は特にエレガントではなく、メンテナンスが不十分なため、一時的な緊急救助にのみ適しています。
プロジェクトにオブジェクトマッピングが必要な場所がたくさんある場合は、一般的なマッパーツールの作成を検討してください。例えば:
<?php
function mapUser($data) {
$user = new User();
$user->id = (int) $data->id;
$user->name = (string) $data->name;
return $user;
}
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT id, name FROM users');
$rawUser = $stmt->fetchObject();
$user = mapUser($rawUser);
var_dump($user);
?>
この方法はより制御可能であり、後の段階で検証ロジックを追加するなど、管理と拡張が簡単です。
データテーブルのフィールドタイプは合理的に設計されています。データベーステーブルのフィールドを可能な限りクリアするようにしてください。たとえば、IDはintでなければならず、金額は小数である必要があります。数値フィールドの代わりに文字列を使用しないでください。
強力な型宣言の使用:PHP 7.4+では、タイプのヒントと属性タイプ宣言を使用すると、エラーを早期に検出できます。
Unified Data Access Layer(DAL)カプセル化:プロジェクトが大きい場合は、繰り返しの労働を避けるために、データベースアクセスとオブジェクトマッピングを統一モジュールにカプセル化することが最善です。
FetchObjectを使用すると非常に便利ですが、正しいデータ型を確保するために、通常、クラスを自分で定義したり、手動変換と協力したり、マッピング機能を使用したりすることをお勧めします。これにより、コードがより堅牢になり、その後のデバッグのトラブルが軽減されます。
より詳細なPDOの使用法とオブジェクトマッピングを知りたい場合は、 https://gitbox.net/docs/pdo-tutorialを参照できます。