发布日期:2024年1月17日 | 作者:PHP高级开发工程师
一、MVC架构模式深度解析
什么是MVC模式?
MVC(Model-View-Controller)是一种软件设计模式,将应用程序分为三个核心组件:
- Model(模型):处理数据和业务逻辑
- View(视图):负责数据展示和用户界面
- Controller(控制器):接收用户输入,协调模型和视图
MVC在PHP中的优势
// 传统过程式编程 vs MVC面向对象编程
// 传统方式 - 混合在一起
<?php
// 连接数据库
$conn = mysqli_connect("localhost", "user", "pass", "blog");
// 查询数据
$result = mysqli_query($conn, "SELECT * FROM posts");
// 显示数据
while($row = mysqli_fetch_assoc($result)) {
echo "<h2>" . $row['title'] . "</h2>";
echo "<p>" . $row['content'] . "</p>";
}
?>
// MVC方式 - 分离关注点
// Controller: 处理请求
// Model: 数据操作
// View: 显示模板
二、项目目录结构设计
标准化目录布局
blog-system/
├── app/
│ ├── controllers/ # 控制器类
│ ├── models/ # 模型类
│ ├── views/ # 视图模板
│ └── core/ # 核心类库
├── config/
│ └── database.php # 数据库配置
├── public/
│ ├── index.php # 入口文件
│ └── assets/ # 静态资源
├── vendor/ # 第三方库
└── .htaccess # URL重写规则
入口文件设计
<?php
// public/index.php
require_once '../app/core/App.php';
require_once '../app/core/Controller.php';
require_once '../app/core/Database.php';
// 自动加载类
spl_autoload_register(function($className) {
$path = '../app/' . str_replace('\', '/', $className) . '.php';
if (file_exists($path)) {
require_once $path;
}
});
// 启动应用
$app = new App();
$app->run();
?>
三、数据库设计与PDO封装
数据库表结构
-- 文章表
CREATE TABLE posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
excerpt TEXT,
author_id INT,
category_id INT,
status ENUM('published', 'draft') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 用户表
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role ENUM('admin', 'author', 'user') DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 分类表
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) UNIQUE NOT NULL
);
PDO数据库封装类
<?php
class Database {
private $host = DB_HOST;
private $user = DB_USER;
private $pass = DB_PASS;
private $dbname = DB_NAME;
private $dbh;
private $stmt;
private $error;
public function __construct() {
$dsn = 'mysql:host=' . $this->host . ';dbname=' . $this->dbname;
$options = array(
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ
);
try {
$this->dbh = new PDO($dsn, $this->user, $this->pass, $options);
} catch(PDOException $e) {
$this->error = $e->getMessage();
echo $this->error;
}
}
public function query($sql) {
$this->stmt = $this->dbh->prepare($sql);
}
public function bind($param, $value, $type = null) {
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue($param, $value, $type);
}
public function execute() {
return $this->stmt->execute();
}
public function resultSet() {
$this->execute();
return $this->stmt->fetchAll();
}
public function single() {
$this->execute();
return $this->stmt->fetch();
}
public function rowCount() {
return $this->stmt->rowCount();
}
}
?>
四、核心类库实现
应用核心类(App.php)
<?php
class App {
protected $controller = 'Home';
protected $method = 'index';
protected $params = [];
public function __construct() {
$url = $this->parseUrl();
// 控制器处理
if (isset($url[0]) && file_exists('../app/controllers/' . ucwords($url[0]) . '.php')) {
$this->controller = ucwords($url[0]);
unset($url[0]);
}
require_once '../app/controllers/' . $this->controller . '.php';
$this->controller = new $this->controller;
// 方法处理
if (isset($url[1])) {
if (method_exists($this->controller, $url[1])) {
$this->method = $url[1];
unset($url[1]);
}
}
// 参数处理
$this->params = $url ? array_values($url) : [];
// 调用控制器方法
call_user_func_array([$this->controller, $this->method], $this->params);
}
public function parseUrl() {
if (isset($_GET['url'])) {
return explode('/', filter_var(rtrim($_GET['url'], '/'), FILTER_SANITIZE_URL));
}
return [];
}
}
?>
基础模型类(Model.php)
<?php
class Model {
protected $db;
protected $table;
protected $primaryKey = 'id';
public function __construct() {
$this->db = new Database();
}
public function all() {
$this->db->query("SELECT * FROM " . $this->table);
return $this->db->resultSet();
}
public function find($id) {
$this->db->query("SELECT * FROM " . $this->table . " WHERE " . $this->primaryKey . " = :id");
$this->db->bind(':id', $id);
return $this->db->single();
}
public function create($data) {
$fields = implode(', ', array_keys($data));
$values = ':' . implode(', :', array_keys($data));
$this->db->query("INSERT INTO " . $this->table . " (" . $fields . ") VALUES (" . $values . ")");
foreach ($data as $key => $value) {
$this->db->bind(':' . $key, $value);
}
return $this->db->execute();
}
public function update($id, $data) {
$set = '';
foreach ($data as $key => $value) {
$set .= $key . " = :" . $key . ", ";
}
$set = rtrim($set, ', ');
$this->db->query("UPDATE " . $this->table . " SET " . $set . " WHERE " . $this->primaryKey . " = :id");
foreach ($data as $key => $value) {
$this->db->bind(':' . $key, $value);
}
$this->db->bind(':id', $id);
return $this->db->execute();
}
public function delete($id) {
$this->db->query("DELETE FROM " . $this->table . " WHERE " . $this->primaryKey . " = :id");
$this->db->bind(':id', $id);
return $this->db->execute();
}
}
?>
五、控制器实战开发
文章控制器(Posts.php)
<?php
class Posts extends Controller {
private $postModel;
public function __construct() {
$this->postModel = $this->model('Post');
}
public function index() {
$posts = $this->postModel->getPublishedPosts();
$data = [
'posts' => $posts,
'title' => '最新文章'
];
$this->view('posts/index', $data);
}
public function show($id) {
$post = $this->postModel->getPostById($id);
if (!$post) {
$this->view('pages/404');
return;
}
$data = [
'post' => $post,
'title' => $post->title
];
$this->view('posts/show', $data);
}
public function create() {
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// 处理表单提交
$data = [
'title' => trim($_POST['title']),
'content' => trim($_POST['content']),
'author_id' => $_SESSION['user_id'],
'category_id' => $_POST['category_id']
];
if ($this->postModel->createPost($data)) {
redirect('posts');
} else {
// 处理错误
$this->view('posts/create', $data);
}
} else {
// 显示创建表单
$data = [
'title' => '',
'content' => ''
];
$this->view('posts/create', $data);
}
}
}
?>
文章模型(Post.php)
<?php
class Post extends Model {
protected $table = 'posts';
public function getPublishedPosts() {
$this->db->query('
SELECT p.*, u.username as author_name, c.name as category_name
FROM posts p
LEFT JOIN users u ON p.author_id = u.id
LEFT JOIN categories c ON p.category_id = c.id
WHERE p.status = "published"
ORDER BY p.created_at DESC
');
return $this->db->resultSet();
}
public function getPostById($id) {
$this->db->query('
SELECT p.*, u.username as author_name, c.name as category_name
FROM posts p
LEFT JOIN users u ON p.author_id = u.id
LEFT JOIN categories c ON p.category_id = c.id
WHERE p.id = :id
');
$this->db->bind(':id', $id);
return $this->db->single();
}
public function createPost($data) {
$this->db->query('
INSERT INTO posts (title, content, author_id, category_id, status)
VALUES (:title, :content, :author_id, :category_id, "published")
');
// 绑定参数
$this->db->bind(':title', $data['title']);
$this->db->bind(':content', $data['content']);
$this->db->bind(':author_id', $data['author_id']);
$this->db->bind(':category_id', $data['category_id']);
return $this->db->execute();
}
}
?>
六、视图模板引擎实现
基础视图类
<?php
class View {
public static function render($view, $data = []) {
// 将数据数组转换为变量
extract($data);
$viewFile = '../app/views/' . $view . '.php';
if (file_exists($viewFile)) {
require_once $viewFile;
} else {
die('视图文件不存在: ' . $view);
}
}
public static function partial($partial, $data = []) {
extract($data);
require_once '../app/views/partials/' . $partial . '.php';
}
}
?>
文章列表视图模板
<!-- app/views/posts/index.php -->
<?php include '../app/views/partials/header.php'; ?>
<div class="container">
<h1><?php echo $data['title']; ?></h1>
<?php if (!empty($data['posts'])): ?>
<div class="posts-list">
<?php foreach ($data['posts'] as $post): ?>
<article class="post-card">
<h2>
<a href="<?php echo URLROOT; ?>/posts/show/<?php echo $post->id; ?>" rel="external nofollow" rel="external nofollow" >
<?php echo htmlspecialchars($post->title); ?>
</a>
</h2>
<div class="post-meta">
<span>作者: <?php echo $post->author_name; ?></span>
<span>分类: <?php echo $post->category_name; ?></span>
<span>发布时间: <?php echo date('Y-m-d', strtotime($post->created_at)); ?></span>
</div>
<p><?php echo nl2br(htmlspecialchars(substr($post->content, 0, 200))); ?>...</p>
<a href="<?php echo URLROOT; ?>/posts/show/<?php echo $post->id; ?>" rel="external nofollow" rel="external nofollow" class="read-more">
阅读更多
</a>
</article>
<?php endforeach; ?>
</div>
<?php else: ?>
<p>暂无文章</p>
<?php endif; ?>
</div>
<?php include '../app/views/partials/footer.php'; ?>
七、高级功能实现
1. 用户认证系统
<?php
class Auth {
public static function login($user) {
$_SESSION['user_id'] = $user->id;
$_SESSION['user_email'] = $user->email;
$_SESSION['user_role'] = $user->role;
}
public static function logout() {
session_unset();
session_destroy();
}
public static function isLoggedIn() {
return isset($_SESSION['user_id']);
}
public static function isAdmin() {
return isset($_SESSION['user_role']) && $_SESSION['user_role'] === 'admin';
}
}
?>
2. 表单验证类
<?php
class Validator {
private $data;
private $errors = [];
public function __construct($post_data) {
$this->data = $post_data;
}
public function validateField($field, $rules) {
$value = trim($this->data[$field]);
foreach ($rules as $rule => $param) {
switch ($rule) {
case 'required':
if (empty($value)) {
$this->addError($field, "{$field} 是必填字段");
}
break;
case 'min':
if (strlen($value) < $param) {
$this->addError($field, "{$field} 至少需要 {$param} 个字符");
}
break;
case 'email':
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->addError($field, "{$field} 必须是有效的邮箱地址");
}
break;
}
}
}
private function addError($field, $message) {
$this->errors[$field] = $message;
}
public function hasErrors() {
return !empty($this->errors);
}
public function getErrors() {
return $this->errors;
}
}
?>
项目总结与部署
系统功能特性
- 完整的MVC架构实现
- 安全的PDO数据库操作
- 用户认证与权限管理
- 响应式前端界面
- 表单验证与错误处理
部署注意事项
# .htaccess 配置
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
进一步优化方向
- 实现RESTful API接口
- 添加缓存机制提升性能
- 实现文件上传功能
- 添加评论系统
- 实现搜索功能