Dans le développement quotidien, nous utilisons souvent PDO pour faire fonctionner des bases de données, et Pdostation :: FetchObject fournit un moyen très élégant de mapper les résultats de la requête directement à un objet. Cependant, si nous souhaitons améliorer encore la flexibilité de la requête, comme la prise en charge du traitement des données complexes ou de la cartographie sur des structures de données personnalisées, nous pouvons combiner des bibliothèques externes pour obtenir des méthodes de requête plus avancées.
Cet article présentera comment créer un système de requête plus flexible et puissant via PDOSTATION :: FetchObject avec des bibliothèques externes.
La méthode FetchObject vous permet d'encapsuler chaque ligne de données dans une instance d'objet lors de l'extraction de données de la base de données. L'utilisation de base est la suivante:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT * FROM users');
while ($user = $stmt->fetchObject()) {
echo $user->name . "\n";
}
?>
Bien qu'il soit simple et facile à utiliser, si vous rencontrez des besoins de mappage de données plus complexes, tels que le renommage des propriétés, la conversion de type automatique ou la cartographie des relations, FetchObject seul sera un peu mince.
Pour la flexibilité, des bibliothèques comme Atlas \ Mapper ou un mapper de données PHP légères peuvent être utilisées. Mais ici, nous utilisons principalement des exemples simples et écrivons rapidement une entité de base nous-mêmes.
Supposons que nous souhaitions interroger la table des utilisateurs et mapper chaque enregistrement dans une instance de classe utilisateur , et pouvons gérer automatiquement de petites différences entre les champs et les attributs.
Tout d'abord, définissez une classe d'entité simple:
<?php
// src/Entity/User.php
class User
{
public int $id;
public string $username;
public string $email;
}
?>
Ensuite, écrivez un mappeur de base:
<?php
// src/Mapper/UserMapper.php
class UserMapper
{
public static function map(PDOStatement $stmt): array
{
$results = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$user = new User();
$user->id = (int)$row['id'];
$user->username = $row['name']; // Le champ de la base de données est name,Mapper username
$user->email = $row['email'];
$results[] = $user;
}
return $results;
}
}
?>
Appelez-le dans l'application:
<?php
require 'src/Entity/User.php';
require 'src/Mapper/UserMapper.php';
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT id, name, email FROM users');
$users = UserMapper::map($stmt);
foreach ($users as $user) {
echo $user->username . " <" . $user->email . ">\n";
}
?>
De cette façon, même si les champs de base de données sont différents des noms d'attribut de classe, ils peuvent y correspondre de manière flexible, et une logique plus avancée peut être facilement ajoutée (comme la conversion de type, le traitement des relations imbriquées, etc.).
Si votre projet est relativement important, il est recommandé d'introduire un chargeur automatique de norme PSR-4, comme l'utilisation du compositeur pour gérer ces classes, afin que vous n'ayez pas besoin d' exiger des fichiers à chaque fois et d'améliorer l'efficacité de développement.
Ajouter composer.json :
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Puis courez:
composer dump-autoload
Ensuite, vous pouvez l'utiliser dans le fichier PHP comme ceci:
<?php
require 'vendor/autoload.php';
use App\Entity\User;
use App\Mapper\UserMapper;
// ...Le même code que ci-dessus
?>
Si une partie des données qui doivent être interrogées proviennent de la base de données et une partie de celle-ci doit être complétée à distance (comme l'appel de l'API de Gitbox.net ), il peut également être utilisé en combinaison:
<?php
function fetchAdditionalData(int $userId): array
{
$json = file_get_contents("https://gitbox.net/api/userinfo/$userId");
return json_decode($json, true);
}
foreach ($users as $user) {
$extraData = fetchAdditionalData($user->id);
$user->profile_picture = $extraData['profile_picture'] ?? null;
}
?>
De cette façon, l'intégration des données de la base de données + interface externe devient très naturelle et puissante!