PDOSTATION :: FetchObject est une méthode très pratique lors de l'exploitation d'une base de données en utilisant PDO en PHP. Il peut renvoyer un enregistrement en tant qu'objet et attribuer la valeur de chaque colonne aux propriétés de l'objet. Cependant, lorsque le type de colonne de la base de données ne correspond pas au type attendu de la propriété d'objet cible, certains problèmes confus peuvent survenir, tels que le type de décalage, les erreurs de conversion implicites ou les exceptions comportementales.
class User {
public int $id;
public string $name;
public bool $is_active;
}
$stmt = $pdo->query('SELECT id, name, is_active FROM users');
$user = $stmt->fetchObject('User');
Supposons que la colonne IS_ACTIVE dans la table des utilisateurs soit un type minuscule (1) , et dans la classe utilisateur , nous définissons le type de bool . Si la valeur d' Is_Active est 1 ou 0 , vous pouvez vous attendre à ce qu'elle soit automatiquement convertie en vrai ou fausse . Mais en réalité, PHP attribuera directement les valeurs de type INT , ce qui entraînera des incohérences de types et même jetera directement des erreurs en mode type strict.
À l'intérieur de FetchObject , le champ de la base de données est mappé aux propriétés de l'objet via __set () ou une affectation directe. Il n'effectue pas de conversion de type, mais attribue directement la valeur en fonction de la valeur d'origine de la base de données. Cela signifie:
La valeur int dans la base de données deviendra php int
Varchar deviendra chaîne
Bien que Tinyint (1) soit souvent utilisé pour les valeurs booléennes, c'est en fait un type entier
Une fois l'invite de type de déclaration (strict_types = 1) ou PHP 8.2+ est renforcé, un décalage de type entraînera une erreur d'exécution.
Une approche sûre consiste à convertir manuellement chaque champ en type approprié après avoir obtenu l'objet. Cette méthode est la plus sûre et la plus lisible.
$user = $stmt->fetchObject('User');
if ($user !== false) {
$user->id = (int)$user->id;
$user->name = (string)$user->name;
$user->is_active = (bool)$user->is_active;
}
FetchObject prend en charge le passage des paramètres du constructeur. Si vous concevez un constructeur qui accepte les données initialisées, vous pouvez implémenter la conversion de type gracieusement:
class User {
public function __construct(
public int $id,
public string $name,
public bool $is_active
) {}
}
$stmt = $pdo->query('SELECT id, name, is_active FROM users');
$user = $stmt->fetchObject('User');
Mais le problème ici est: si l'ordre de colonne de base de données est incohérent ou si les champs ne correspondent pas exactement, une exception peut être lancée.
Si le volume de données est important ou si la structure de l'objet est complexe, envisagez d'utiliser une classe d'usine pour gérer la logique de transformation.
class UserFactory {
public static function fromDb(stdClass $row): User {
return new User(
(int)$row->id,
(string)$row->name,
(bool)$row->is_active
);
}
}
$stmt = $pdo->query('SELECT id, name, is_active FROM users');
$row = $stmt->fetchObject();
if ($row !== false) {
$user = UserFactory::fromDb($row);
}
Bien que cela ait plus de code, la structure est claire et la logique est centralisée, ce qui facilite les tests et la maintenance unitaires.
Vous pouvez également utiliser PDO :: fetch_class | Mode PDO :: fetch_props_late , mais vous devez également faire attention au problème de conversion de type. PHP ne fait pas d'inférence de type en interne.
$stmt = $pdo->query('SELECT id, name, is_active FROM users');
$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'User');
$user = $stmt->fetch();
Comme mentionné ci-dessus, bien que le code soit simplifié, il ne peut toujours pas résoudre le problème du type obligatoire.
Lorsque vous utilisez PDOSTATION :: FetchObject pour l'extraction d'objets, assurez-vous de faire attention à la correspondance entre les types de champs de base de données et les types d'attribut d'objets. PHP n'effectue pas automatiquement des conversions intelligentes, surtout après avoir allumé l'invite de type, les développeurs doivent gérer explicitement la logique de conversion. Le moyen le plus recommandé est de découpler l'extraction des données et la construction d'objets, comme l'utilisation de classes d'usine ou de transformations manuelles, améliorant ainsi la robustesse et la maintenabilité de votre code.
Pour des exemples plus connexes, veuillez vous référer à: https://gitbox.net/pdo/fetchobject-type-conversion