index.php必须是唯一入口,否则路由失效、全局配置不生效、自动加载混乱;它定义关键常量、注册自动加载器、设置错误报告,并由router解析request_uri映射url到控制器方法,模型层禁止输出,视图层应明确使用require/include区分必需与可选文件。

index.php 必须是唯一入口,否则路由失效、全局配置不生效、自动加载混乱——这是所有 PHP MVC 实操失败的起点。
为什么 index.php 不能被绕过
常见错误现象:直接访问 controller/UserController.php 或在浏览器里手动拼 /app/Models/UserModel.php,结果报错、空白页、或数据库连接失败。
根本原因不是代码写错了,而是缺失了 MVC 的运行上下文:常量未定义、自动加载器没注册、数据库连接未初始化、错误报告级别未设置。
-
index.php负责定义APP_PATH、CONFIG_PATH等关键常量,其他文件依赖这些路径加载资源 - 它调用
require_once 'vendor/autoload.php'(或手动注册spl_autoload_register),没有它,new UserController()就会触发Fatal error: Class 'UserController' not found - 它统一设置
error_reporting(E_ALL)和异常处理器,绕过它等于在生产环境裸奔
Router->dispatch() 怎么匹配 URL 到控制器方法
不是靠文件名硬匹配,而是解析 $_SERVER['REQUEST_URI'] 后做规则映射。例如访问 /user/profile/123,典型处理流程是:
- 去掉 public 目录前缀和查询参数,得到干净路径
/user/profile/123 - 按约定拆解为
controller(user)、action(profile)、id(123) - 拼类名
UserController,检查该文件是否存在、是否可实例化 - 调用
(new UserController)->profile(123),而非profile()静态方法(避免单例陷阱)
容易踩的坑:Router 类里没过滤 .. 路径遍历,导致攻击者能构造 /../../etc/passwd;或没校验控制器类名是否含非法字符,引发类注入。
模型层为什么不能 echo 或 header
UserModel::getById(5) 返回数组或对象即可,任何输出行为(echo、header()、exit)都会破坏分层契约。
后果很直接:
- 控制器无法捕获数据做缓存、日志或权限校验
- 视图层无法复用同一份数据渲染 HTML / JSON / XML 多种格式
- 单元测试时,
ob_start()拦截输出变得不可靠,断言失败难定位
正确做法:模型只管查库、校验、组装数据;控制器决定“要不要返回”“返回什么格式”;视图只管“怎么展示”。三者之间只能传数据,不能传控制流。
视图文件里 include 和 require 的区别真重要吗
重要,且直接影响错误排查效率。
include 'header.php' 找不到文件只报 Warning,脚本继续执行,最终可能输出半截 HTML;require 'layout.php' 找不到则直接 Fatal error 中断,立刻暴露缺失模板。
- 推荐对核心布局文件(如
layout.php、footer.php)用require - 对可选组件(如广告位
ad_banner.php、统计脚本ga.php)用include - 永远不要在视图里写
require_once '../model/UserModel.php'—— 这违反了“视图不该知道模型存在”的原则
最易被忽略的一点:视图中所有变量都来自控制器显式传入(如 $data['user']),而不是靠 extract($data) 自动导入——后者会让变量来源模糊,调试时根本不知道 $user 是哪来的。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











