本文目录导读:

我来详细讲解PHP模型层的设计原则和最佳实践。
基础模型架构
单一职责原则的模型设计
<?php
// 基础模型类
abstract class BaseModel
{
protected PDO $db;
protected string $table;
protected string $primaryKey = 'id';
public function __construct(PDO $db)
{
$this->db = $db;
}
// 通用CRUD操作
public function find(int $id): ?array
{
$sql = "SELECT * FROM {$this->table} WHERE {$this->primaryKey} = :id";
$stmt = $this->db->prepare($sql);
$stmt->execute(['id' => $id]);
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
}
public function findAll(array $conditions = []): array
{
$sql = "SELECT * FROM {$this->table}";
$params = [];
if (!empty($conditions)) {
$where = [];
foreach ($conditions as $field => $value) {
$where[] = "{$field} = :{$field}";
$params[$field] = $value;
}
$sql .= " WHERE " . implode(' AND ', $where);
}
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
public function create(array $data): int
{
$fields = implode(', ', array_keys($data));
$placeholders = implode(', ', array_map(fn($key) => ":{$key}", array_keys($data)));
$sql = "INSERT INTO {$this->table} ({$fields}) VALUES ({$placeholders})";
$stmt = $this->db->prepare($sql);
$stmt->execute($data);
return (int)$this->db->lastInsertId();
}
public function update(int $id, array $data): bool
{
$sets = [];
foreach ($data as $field => $value) {
$sets[] = "{$field} = :{$field}";
}
$sql = "UPDATE {$this->table} SET " . implode(', ', $sets)
. " WHERE {$this->primaryKey} = :id";
$data['id'] = $id;
$stmt = $this->db->prepare($sql);
return $stmt->execute($data);
}
public function delete(int $id): bool
{
$sql = "DELETE FROM {$this->table} WHERE {$this->primaryKey} = :id";
$stmt = $this->db->prepare($sql);
return $stmt->execute(['id' => $id]);
}
}
业务模型设计
实体模型(Entity)
<?php
class UserEntity
{
private ?int $id;
private string $name;
private string $email;
private ?string $phone;
private DateTime $createdAt;
// 构造函数
public function __construct(array $data = [])
{
$this->id = $data['id'] ?? null;
$this->name = $data['name'] ?? '';
$this->email = $data['email'] ?? '';
$this->phone = $data['phone'] ?? null;
$this->createdAt = isset($data['created_at'])
? new DateTime($data['created_at'])
: new DateTime();
}
// Getters
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function getEmail(): string
{
return $this->email;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function getCreatedAt(): DateTime
{
return $this->createdAt;
}
// Setters with validation
public function setName(string $name): void
{
if (strlen($name) < 2 || strlen($name) > 50) {
throw new InvalidArgumentException('Name must be between 2 and 50 characters');
}
$this->name = $name;
}
public function setEmail(string $email): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException('Invalid email format');
}
$this->email = $email;
}
// 转换为数组
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'phone' => $this->phone,
'created_at' => $this->createdAt->format('Y-m-d H:i:s')
];
}
}
业务模型(Repository模式)
<?php
interface UserRepositoryInterface
{
public function findById(int $id): ?UserEntity;
public function findByEmail(string $email): ?UserEntity;
public function findAll(): array;
public function save(UserEntity $user): UserEntity;
public function delete(int $id): bool;
public function searchUsers(string $keyword): array;
}
class UserRepository extends BaseModel implements UserRepositoryInterface
{
protected string $table = 'users';
public function findById(int $id): ?UserEntity
{
$data = $this->find($id);
return $data ? new UserEntity($data) : null;
}
public function findByEmail(string $email): ?UserEntity
{
$sql = "SELECT * FROM {$this->table} WHERE email = :email";
$stmt = $this->db->prepare($sql);
$stmt->execute(['email' => $email]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
return $data ? new UserEntity($data) : null;
}
public function findAll(): array
{
$results = parent::findAll();
return array_map(fn($data) => new UserEntity($data), $results);
}
public function save(UserEntity $user): UserEntity
{
$data = $user->toArray();
if ($user->getId()) {
$this->update($user->getId(), $data);
} else {
unset($data['id']);
$id = $this->create($data);
$user = $this->findById($id);
}
return $user;
}
public function searchUsers(string $keyword): array
{
$sql = "SELECT * FROM {$this->table}
WHERE name LIKE :keyword
OR email LIKE :keyword";
$stmt = $this->db->prepare($sql);
$stmt->execute(['keyword' => "%{$keyword}%"]);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return array_map(fn($data) => new UserEntity($data), $results);
}
}
业务逻辑服务层
<?php
class UserService
{
private UserRepositoryInterface $userRepository;
private ValidationService $validator;
private EventDispatcher $eventDispatcher;
public function __construct(
UserRepositoryInterface $userRepository,
ValidationService $validator,
EventDispatcher $eventDispatcher
) {
$this->userRepository = $userRepository;
$this->validator = $validator;
$this->eventDispatcher = $eventDispatcher;
}
public function registerUser(array $userData): UserEntity
{
// 数据验证
$this->validator->validate($userData, [
'name' => 'required|min:2|max:50',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed'
]);
// 检查邮箱唯一性
if ($this->userRepository->findByEmail($userData['email'])) {
throw new DuplicateEmailException('Email already exists');
}
// 密码加密
$userData['password_hash'] = password_hash(
$userData['password'],
PASSWORD_BCRYPT
);
unset($userData['password']);
// 创建用户实体
$user = new UserEntity($userData);
// 保存用户
$savedUser = $this->userRepository->save($user);
// 触发事件
$this->eventDispatcher->dispatch(
new UserRegisteredEvent($savedUser)
);
return $savedUser;
}
public function updateProfile(int $userId, array $profileData): UserEntity
{
$user = $this->userRepository->findById($userId);
if (!$user) {
throw new UserNotFoundException('User not found');
}
// 更新字段
if (isset($profileData['name'])) {
$user->setName($profileData['name']);
}
if (isset($profileData['phone'])) {
$user->setPhone($profileData['phone']);
}
// 保存更新
return $this->userRepository->save($user);
}
}
高级模式:查询构建器
<?php
class QueryBuilder
{
private PDO $db;
private string $from;
private array $selects = ['*'];
private array $wheres = [];
private array $joins = [];
private array $orderBys = [];
private ?int $limit = null;
private ?int $offset = null;
private array $params = [];
public function __construct(PDO $db, string $table)
{
$this->db = $db;
$this->from = $table;
}
public function select(array $fields): self
{
$this->selects = $fields;
return $this;
}
public function where(string $field, string $operator, $value): self
{
$paramName = str_replace('.', '_', $field) . '_' . count($this->wheres);
$this->wheres[] = "{$field} {$operator} :{$paramName}";
$this->params[$paramName] = $value;
return $this;
}
public function join(string $table, string $first, string $operator, string $second): self
{
$this->joins[] = "JOIN {$table} ON {$first} {$operator} {$second}";
return $this;
}
public function orderBy(string $field, string $direction = 'ASC'): self
{
$this->orderBys[] = "{$field} {$direction}";
return $this;
}
public function limit(int $limit): self
{
$this->limit = $limit;
return $this;
}
public function offset(int $offset): self
{
$this->offset = $offset;
return $this;
}
public function get(): array
{
$sql = $this->buildSelect();
$stmt = $this->db->prepare($sql);
$stmt->execute($this->params);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
private function buildSelect(): string
{
$sql = "SELECT " . implode(', ', $this->selects)
. " FROM {$this->from}";
if (!empty($this->joins)) {
$sql .= " " . implode(' ', $this->joins);
}
if (!empty($this->wheres)) {
$sql .= " WHERE " . implode(' AND ', $this->wheres);
}
if (!empty($this->orderBys)) {
$sql .= " ORDER BY " . implode(', ', $this->orderBys);
}
if ($this->limit !== null) {
$sql .= " LIMIT {$this->limit}";
}
if ($this->offset !== null) {
$sql .= " OFFSET {$this->offset}";
}
return $sql;
}
}
数据验证层
<?php
trait Validatable
{
private array $errors = [];
public function validate(array $rules): bool
{
$this->errors = [];
foreach ($rules as $field => $validations) {
$validations = explode('|', $validations);
foreach ($validations as $validation) {
// 解析验证规则
if (strpos($validation, ':') !== false) {
[$rule, $parameter] = explode(':', $validation);
} else {
$rule = $validation;
$parameter = null;
}
// 执行验证
$methodName = 'validate' . ucfirst($rule);
if (method_exists($this, $methodName)) {
if (!$this->$methodName($this->$field, $parameter)) {
$this->errors[$field][] = "Field {$field} failed {$rule} validation";
}
}
}
}
return empty($this->errors);
}
private function validateRequired($value): bool
{
return !empty($value);
}
private function validateEmail($value): bool
{
return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
}
private function validateMin($value, $min): bool
{
return strlen($value) >= (int)$min;
}
public function getErrors(): array
{
return $this->errors;
}
}
最佳实践总结
设计原则
- 单一职责:每个模型只负责一个业务领域
- 依赖注入:通过构造函数注入依赖
- 接口编程:定义接口,实现松耦合
- 实体与数据分离:Entity和Repository分离
层次结构
Controller
↓
Service (业务逻辑)
↓
Repository (数据访问)
↓
Entity (数据实体)
注意事项
- 避免在模型层写SQL,使用查询构建器
- 使用类型提示和返回类型声明
- 实现数据库事务管理
- 添加适当的日志记录
- 进行单元测试覆盖
这样设计的模型层具有良好的可扩展性、可维护性和测试性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播