本文目录导读:

- 最简单:使用PDO封装(适合小项目)
- ActiveRecord模式(熟悉但易混淆)
- Data Mapper模式(复杂但干净)
- 实战推荐:基于PDO的仓库(Repository)模式
- 完整项目结构建议
- 使用第三方ORM(生产推荐)
- 关键注意事项
- 选择建议
在PHP项目中实现数据模型,通常有三种主流方式:原生PDO封装、ActiveRecord模式、Data Mapper模式,下面我会从基础到进阶,给出完整的实现方案和代码示例。
最简单:使用PDO封装(适合小项目)
这是最轻量的方式,适合没有ORM框架的简单项目。
// User.php - 数据模型类
class User {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function find($id) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function findByEmail($email) {
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE email = ?');
$stmt->execute([$email]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
public function create(array $data) {
$sql = 'INSERT INTO users (name, email, password) VALUES (?, ?, ?)';
$stmt = $this->pdo->prepare($sql);
return $stmt->execute([
$data['name'],
$data['email'],
password_hash($data['password'], PASSWORD_DEFAULT)
]);
}
}
使用示例:
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$userModel = new User($pdo);
$user = $userModel->findByEmail('user@example.com');
ActiveRecord模式(熟悉但易混淆)
Laravel的Eloquent、ThinkPHP的Model都采用此模式。
// User.php - 使用ActiveRecord模式
class User {
protected $pdo;
protected $table = 'users';
public $id;
public $name;
public $email;
public function __construct(PDO $pdo, array $data = []) {
$this->pdo = $pdo;
foreach ($data as $key => $value) {
if (property_exists($this, $key)) {
$this->$key = $value;
}
}
}
// 查找并返回模型实例
public static function find(PDO $pdo, $id) {
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
return $data ? new self($pdo, $data) : null;
}
// 保存当前实例(插入或更新)
public function save() {
if ($this->id) {
// 更新
$stmt = $this->pdo->prepare(
"UPDATE users SET name = ?, email = ? WHERE id = ?"
);
return $stmt->execute([$this->name, $this->email, $this->id]);
} else {
// 插入
$stmt = $this->pdo->prepare(
"INSERT INTO users (name, email) VALUES (?, ?)"
);
$result = $stmt->execute([$this->name, $this->email]);
if ($result) {
$this->id = $this->pdo->lastInsertId();
}
return $result;
}
}
// 删除
public function delete() {
if (!$this->id) return false;
$stmt = $this->pdo->prepare("DELETE FROM users WHERE id = ?");
return $stmt->execute([$this->id]);
}
}
Data Mapper模式(复杂但干净)
像Doctrine 2采用此模式,模型完全与数据库解耦。
// 1. 实体类 - 纯数据对象
class UserEntity {
private $id;
private $name;
private $email;
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; }
}
// 2. 映射器 - 负责数据库操作
class UserMapper {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function find($id): ?UserEntity {
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$id]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$data) return null;
$user = new UserEntity();
$user->setId($data['id']); // 需要额外加setId方法
$user->setName($data['name']);
$user->setEmail($data['email']);
return $user;
}
public function save(UserEntity $user) {
$id = $user->getId();
if ($id) {
$stmt = $this->pdo->prepare("UPDATE users SET name=?, email=? WHERE id=?");
return $stmt->execute([$user->getName(), $user->getEmail(), $id]);
} else {
$stmt = $this->pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$result = $stmt->execute([$user->getName(), $user->getEmail()]);
if ($result) {
$user->setId($this->pdo->lastInsertId());
}
return $result;
}
}
}
实战推荐:基于PDO的仓库(Repository)模式
这是目前最推荐的实践方式,结合了简洁与清晰。
// repositories/UserRepository.php
class UserRepository {
private $pdo;
public function __construct(PDO $pdo) {
$this->pdo = $pdo;
}
public function findById($id): ?array {
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE id = ? AND deleted_at IS NULL");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
}
public function findByEmail($email): ?array {
$stmt = $this->pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
}
public function findAll(int $page = 1, int $perPage = 20): array {
$offset = ($page - 1) * $perPage;
$stmt = $this->pdo->prepare(
"SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?"
);
$stmt->execute([$perPage, $offset]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function save(array $data): int {
$stmt = $this->pdo->prepare(
"INSERT INTO users (name, email, password, created_at) VALUES (?, ?, ?, NOW())"
);
$stmt->execute([
$data['name'],
$data['email'],
password_hash($data['password'], PASSWORD_DEFAULT)
]);
return (int)$this->pdo->lastInsertId();
}
public function update($id, array $data): bool {
$sets = [];
$values = [];
foreach ($data as $key => $value) {
$sets[] = "$key = ?";
$values[] = $value;
}
$values[] = $id;
$sql = "UPDATE users SET " . implode(', ', $sets) . " WHERE id = ?";
return $this->pdo->prepare($sql)->execute($values);
}
public function delete($id): bool {
$stmt = $this->pdo->prepare("DELETE FROM users WHERE id = ?");
return $stmt->execute([$id]);
}
}
完整项目结构建议
your-project/
├── src/
│ ├── Models/ # 数据模型(实体类,可选)
│ │ └── UserEntity.php
│ ├── Repositories/ # 仓库层(数据访问)
│ │ └── UserRepository.php
│ ├── Services/ # 业务逻辑层
│ │ └── UserService.php
│ └── Database/ # 数据库连接
│ └── Connection.php
├── config/
│ └── database.php
└── public/
└── index.php
使用第三方ORM(生产推荐)
如果项目规模较大,建议直接使用成熟的ORM:
Laravel + Eloquent
// 模型定义
class User extends Model {
protected $fillable = ['name', 'email', 'password'];
public function posts() {
return $this->hasMany(Post::class);
}
}
// 使用
$user = User::find(1);
$user->name = 'New Name';
$user->save();
MySQLi基础封装(最简方案)
class Db {
private static $instance;
private $mysqli;
private function __construct() {
$this->mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
}
public static function table($table) {
self::getInstance()->table = $table;
return self::getInstance();
}
public function find($id) {
$stmt = $this->mysqli->prepare("SELECT * FROM {$this->table} WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
return $stmt->get_result()->fetch_assoc();
}
}
关键注意事项
- SQL注入防护:永远使用预处理语句(prepare + execute)
- 连接管理:生产环境使用连接池或单例模式
- 数据验证:在模型中做基础验证,在Service层做业务验证
- 异常处理:统一封装成自定义异常类
- 性能考虑:对于复杂查询,使用查询构建器而不是纯SQL拼接
选择建议
- 项目<5万行代码:PDO封装 + Repository模式足够
- 中大型项目:使用Laravel的Eloquent或Symfony的Doctrine
- 微服务:可以考虑轻量级的Medoo或NotORM
- 追求极致性能:手写PDO + 简单的ActiveRecord模式
最重要的是保持一致性:整个团队使用同一模式,并且数据访问层与业务逻辑层充分分离。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播