mvc架构是职责划分约定:model处理数据与业务规则,view仅负责纯模板渲染,controller只做请求调度;三者严格分离,model校验密码等规则、view禁用数据库直连和超全局变量、controller不写业务逻辑。

PHP里所谓“MVC架构”,不是一套固定代码,而是一套职责划分约定:Model管数据和规则,View管纯展示,Controller只做调度。照着做,代码才不容易散架;不照着分,哪怕用Laravel也迟早变成“一锅炖”。
Model 层该放什么、不该放什么
Model 不是数据库操作封装器,而是业务规则的守门人。用户注册时密码强度校验、邮箱唯一性检查、订单金额合法性判断——这些必须在 Model 方法里完成,不能甩给 Controller 处理。
- ✅ 正确:UserModel::register($data) 内部调用
password_hash()、查库验证邮箱、抛出InvalidArgumentException - ❌ 错误:Controller 里写
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)),再传给空壳 Model - ⚠️ 容易踩的坑:Model 类里直接 echo 或 header() —— 这会让单元测试无法运行,也破坏了“只返回数据、不输出内容”的契约
- ? 性能提示:Model 方法应返回数组或 DTO 对象,避免返回
PDOStatement或未 fetch 的结果集,否则 View 里可能意外触发查询
View 必须是“哑”的,不能有逻辑
View 文件(比如 user/profile.php)只能做两件事:接收 Controller 显式传入的变量,然后用 HTML + PHP 短标签输出。任何数据库调用、超全局变量访问、new 实例化,都是越界。
- ✅ 正确:
echo htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8');—— 仅转义并输出已传入的变量 - ❌ 错误:
$model = new UserModel(); $user = $model->getById($_GET['id']);—— 绕过 Controller,破坏请求生命周期 - ⚠️ 容易踩的坑:在 View 里用
require_once 'config/database.php'手动连库,导致缓存失效、权限绕过、SQL 注入风险放大 - ? 兼容性注意:原生 PHP View 中避免用短标签
=(除非short_open_tag明确开启),改用<?php echo更稳妥
Controller 是调度员,不是业务员
Controller 的唯一任务是:收请求 → 验证参数 → 调 Model → 选 View → 传数据。它不该处理密码加密、文件尺寸校验、时间格式化等具体逻辑,那些都该下沉到 Model 或独立 Service 类。
- ✅ 正确:
$user = $this->userService->create($validatedData);—— 把活交给专门类 - ❌ 错误:在
UserController::store()里写 20 行正则匹配手机号、计算头像路径、生成邀请码 - ⚠️ 容易踩的坑:
$_FILES直接传给 Model —— Controller 必须先调用is_uploaded_file()和move_uploaded_file()做基础校验与移动,再把安全路径传下去 - ? 参数差异:Laravel 的
$request->validate()自动过滤并返回清洗后数据;原生项目得手动用filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL),漏一步就埋雷
真正难的从来不是写出三层目录结构,而是每次加新功能时,下意识问自己:这段 if 判断该在 Model 里抛异常,还是在 Controller 里跳转,抑或在 View 里用 class 控制显隐?答案错了,MVC 就只是目录名而已。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











