本文目录导读:

我来详细解释PHP中的数据映射(Data Mapping)模式:
什么是数据映射模式
数据映射器是一种架构模式,用于在对象和数据库之间进行双向数据转换,让对象和数据库结构保持独立。
基本实现方式
基础数据映射器示例
<?php
// 实体类
class User {
private $id;
private $name;
private $email;
public function __construct($id = null, $name = null, $email = null) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
}
// Getters and Setters
public function getId() { return $this->id; }
public function getName() { return $this->name; }
public function setName($name) { $this->name = $name; }
public function getEmail() { return $this->email; }
public function setEmail($email) { $this->email = $email; }
}
// 数据映射器
class UserMapper {
private $db;
public function __construct(PDO $db) {
$this->db = $db;
}
// 从数据库加载对象
public function find($id) {
$stmt = $this->db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) return null;
return new User(
$row['id'],
$row['name'],
$row['email']
);
}
// 保存对象到数据库
public function save(User $user) {
if ($user->getId()) {
// 更新
$stmt = $this->db->prepare("UPDATE users SET name=?, email=? WHERE id=?");
$stmt->execute([
$user->getName(),
$user->getEmail(),
$user->getId()
]);
} else {
// 插入
$stmt = $this->db->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute([
$user->getName(),
$user->getEmail()
]);
$user->setId($this->db->lastInsertId());
}
}
// 删除对象
public function delete(User $user) {
$stmt = $this->db->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$user->getId()]);
}
}
使用示例
<?php
// 使用数据映射器
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
$userMapper = new UserMapper($pdo);
// 查找用户
$user = $userMapper->find(1);
echo $user->getName();
// 修改用户
$user->setName('New Name');
$userMapper->save($user);
// 创建新用户
$newUser = new User(null, 'John', 'john@example.com');
$userMapper->save($newUser);
// 删除用户
$userMapper->delete($user);
高级数据映射器模式
<?php
// 抽象映射器
abstract class AbstractMapper {
protected $db;
protected $table;
public function __construct(PDO $db, $table) {
$this->db = $db;
$this->table = $table;
}
public function find($id) {
$stmt = $this->db->prepare("SELECT * FROM {$this->table} WHERE id = ?");
$stmt->execute([$id]);
return $this->mapRowToObject($stmt->fetch(PDO::FETCH_ASSOC));
}
public function findAll() {
$stmt = $this->db->query("SELECT * FROM {$this->table}");
$objects = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$objects[] = $this->mapRowToObject($row);
}
return $objects;
}
abstract protected function mapRowToObject($row);
abstract protected function mapObjectToRow($object);
public function save($object) {
$row = $this->mapObjectToRow($object);
if ($object->getId()) {
$this->update($row, $object->getId());
} else {
$this->insert($row);
$object->setId($this->db->lastInsertId());
}
}
private function insert($row) {
$columns = implode(', ', array_keys($row));
$placeholders = implode(', ', array_fill(0, count($row), '?'));
$stmt = $this->db->prepare("INSERT INTO {$this->table} ($columns) VALUES ($placeholders)");
$stmt->execute(array_values($row));
}
private function update($row, $id) {
$sets = implode('=?, ', array_keys($row)) . '=?';
$values = array_values($row);
$values[] = $id;
$stmt = $this->db->prepare("UPDATE {$this->table} SET $sets WHERE id=?");
$stmt->execute($values);
}
}
// 具体实现
class ProductMapper extends AbstractMapper {
public function __construct(PDO $db) {
parent::__construct($db, 'products');
}
protected function mapRowToObject($row) {
if (!$row) return null;
return new Product(
$row['id'],
$row['name'],
$row['price'],
$row['category_id']
);
}
protected function mapObjectToRow($object) {
return [
'name' => $object->getName(),
'price' => $object->getPrice(),
'category_id' => $object->getCategoryId()
];
}
}
使用Doctrine ORM(流行的PHP数据映射工具)
<?php
// 使用Doctrine ORM
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User {
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue */
private $id;
/** @ORM\Column(type="string") */
private $name;
/** @ORM\Column(type="string", unique=true) */
private $email;
// Getters and setters...
}
// 使用
$user = $entityManager->find('User', 1);
$user->setName('New Name');
$entityManager->flush();
数据映射的优点
- 分离关注点 - 业务逻辑与数据访问分离
- 测试便利 - 可以独立测试实体和映射器
- 灵活性 - 可以更改数据库结构而不影响业务代码
- 重用性 - 映射器可以在不同地方重用
常见的PHP数据映射框架
- Doctrine ORM - 最流行的PHP ORM
- Eloquent ORM - Laravel的ORM
- Propel - 另一个流行的ORM
- RedBeanPHP - 零配置ORM
数据映射模式在处理复杂的数据关系时特别有用,能帮助你保持代码的清洁和可维护性。