データベース開発にPHPを使用する場合、 pdostatement :: fetchObjectは、クエリの結果をオブジェクトに直接マッピングできる非常に実用的な方法です。ただし、PHP 5およびPHP 7では、 FetchObjectの動作には微妙だが重要な違いがあります。これらの互換性の問題を理解できないため、異なるバージョンのコードに予期せぬエラーが発生する可能性があります。
この記事では、これらの違いを深く説明し、理解するための実際のコード例を提供します。
pdostatement :: fetchObjectの基本的な使用法は、結果セットから行をオブジェクトとして取得することです。
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT id, name FROM users');
$user = $stmt->fetchObject();
echo $user->id;
echo $user->name;
?>
デフォルトのリターンは、 stdclassオブジェクトです。もちろん、データを受信するカスタムクラス名を指定することもできます。
PHP 5 :オブジェクトがインスタンス化された後、属性が割り当てられた後にコンストラクター(__construct)が呼び出されます。
PHP 7 :オブジェクトがインスタンス化されると、属性が割り当てられる前にコンストラクターが最初に呼び出されます。
これは重要な問題につながります。コンストラクターが特定のフィールドの初期化に依存している場合、PHP 5とPHP 7で完全に異なる動作をする可能性があります。
単純なクラスがあるとします:
<?php
class User {
public $id;
public $name;
public function __construct() {
echo "コンストラクターが呼び出されます:id = {$this->id}, name = {$this->name}\n";
}
}
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->query('SELECT id, name FROM users LIMIT 1');
$user = $stmt->fetchObject('User');
?>
PHP 5では、出力は次のとおりです。
コンストラクターが呼び出されます:id = 1, name = John
PHP 7では、出力は次のとおりです。
コンストラクターが呼び出されます:id = , name =
PHP 7が属性の割り当ての前にコンストラクターを呼び出すからです!
PHP 5および7では、 FetchObjectメソッドの署名はわずかに異なります。
fetchObject ([ string $class_name = "stdClass" [, array $ctor_args = array() ]] ) : object
PHP 5 :サポート$ class_nameおよび$ ctor_args
PHP 7 : $ class_nameと$ ctor_argsもサポートしていますが、php 7.2の後、パラメータータイプの検証はより厳しくなります。たとえば、 $ ctor_argsは配列でなければなりません。
2番目のパラメーターとして非アレイをPHP 7に渡すと、 TypeRrorエラーに直接連絡します。
<?php
// エラーデモンストレーション(PHP 7.2+ エラーが報告されます)
$user = $stmt->fetchObject('User', '間違っているctor_args');
?>
それを書く正しい方法は次のとおりです。
<?php
$user = $stmt->fetchObject('User', ['パラメーター1', 'パラメーター2']);
?>
PHP 5 :指定された$ class_nameが存在しない場合、 fetchobjectはfalseを返すだけです。
PHP 7 :指定された$ class_nameが存在しない場合、エラー例外が直接スローされます!
したがって、PHP 7では、 $ class_nameが正しくロードされていることを確認する必要があります。そうしないと、コードが破損します。
安全なアプローチは次のとおりです。
<?php
$className = 'User';
if (class_exists($className)) {
$user = $stmt->fetchObject($className);
} else {
throw new Exception("親切 {$className} 存在しません");
}
?>
クラスコンストラクターのデータベースフィールドに依存している場合は、PHP 7の初期化ロジックを再検討して、コンストラクターにまだ割り当てられていないプロパティを直接使用しないようにしてください。
$ CTOR_ARGSに渡された配列が、PHP 7.2後のタイプエラーを防ぐためのアレイであることを確認してください。
FetchObjectを呼び出す前に、 class_existsを使用して、クラスが存在するかどうかを確認して堅牢性を向上させます。
PHP 5とPHP 7と互換性がある必要がある場合は、単純なSTDCLASSを均一に使用し、必要なオブジェクトに手動で割り当てることをお勧めします。