在 Web 开发中,404 Not Found 页面是网站不可或缺的基础组件。一个友好的自定义 404 页面,不仅能提升用户体验,还能避免暴露框架底层报错信息,兼顾 SEO 与网站安全性。
Yaf 作为轻量、高性能的 PHP 框架,并没有内置可视化的 404 页面,而是通过异常机制处理未找到的请求(控制器 / 动作不存在)。本文将带你从零实现 Yaf 框架 404 页面的自定义,从基础配置到全局优雅处理,覆盖新手到进阶的全场景需求。
一、Yaf 默认的 404 响应(不推荐)
当用户访问不存在的控制器或不存在的动作方法时,Yaf 会直接抛出 Yaf_Exception_NotFound 异常。
默认效果:
- 开发环境:直接输出异常堆栈信息,暴露框架路径、代码细节;
- 生产环境:空白页面或极简的
Not Found文本,用户体验极差。
这显然无法满足生产环境需求,因此我们需要自定义 404 页面。
二、核心原理
Yaf 处理 404 的核心逻辑:
请求无法匹配到合法的控制器 / 动作 → 抛出
Yaf_Exception_NotFound异常 → 捕获该异常 → 转发到自定义的 404 页面
前置配置
首先修改 Yaf 的核心配置文件 conf/application.ini,开启异常抛出(必须配置):
ini
[common]
application.directory = APP_PATH "/application"
application.view.ext = "phtml"
; 👇 关键配置:开启异常抛出,允许我们手动捕获404
application.dispatcher.throwException = 1
; 关闭框架自动捕获异常(自定义处理时必选)
application.dispatcher.catchException = 0
[product : common]
; 生产环境关闭报错
display_errors = 0
三、基础实战:自定义 404 控制器 + 视图
这是最常用、最简单的实现方式,适合中小型项目。
步骤 1:创建 404 控制器
在 application/controllers/ 目录下,创建 Error.php 控制器(专门处理异常 / 404):
php
运行
<?php
/**
* 异常控制器:处理404、系统错误
*/
class ErrorController extends Yaf_Controller_Abstract
{
/**
* 404页面动作
*/
public function errorAction()
{
// ✅ 核心:设置HTTP 404状态码(SEO必须,否则搜索引擎视为正常页面)
http_response_code(404);
// 如果项目使用了布局模板,禁用布局(纯404页面)
$this->_view->setLayout(false);
// 可选:传递404提示信息到视图
$this->_view->message = '您访问的页面不存在或已被删除';
}
}
步骤 2:创建 404 视图模板
在 application/views/error/ 目录下,创建 error.phtml 视图文件:
html
预览
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - 页面不存在</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f5f5f5; font-family: "Microsoft YaHei"; }
.container {
max-width: 600px;
margin: 100px auto;
text-align: center;
padding: 40px 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 { font-size: 60px; color: #ff4d4f; margin-bottom: 20px; }
p { font-size: 18px; color: #666; margin-bottom: 30px; }
a {
display: inline-block;
padding: 10px 20px;
background: #1890ff;
color: #fff;
border-radius: 4px;
text-decoration: none;
}
</style>
</head>
<body>
<div class="container">
<h1>404</h1>
<p><?= $this->message ?></p>
<a href="/">返回首页</a>
</div>
</body>
</html>
步骤 3:捕获 404 异常(入口文件)
修改项目入口文件 public/index.php,通过 try-catch 捕获 404 异常,并转发到我们的自定义页面:
php
运行
<?php
// 定义应用根目录
define('APP_PATH', dirname(__DIR__));
// 加载Yaf框架(根据你的项目自动加载配置调整)
require APP_PATH . '/vendor/autoload.php';
// 初始化Yaf应用
$app = new Yaf_Application(APP_PATH . '/conf/application.ini');
try {
// 执行应用
$app->run();
} catch (Yaf_Exception_NotFound $e) {
// 👇 捕获404异常,转发到Error控制器的errorAction
$dispatcher = Yaf_Dispatcher::getInstance();
$dispatcher->dispatch(new Yaf_Request_Simple('HTTP', 'Error', 'error'));
} catch (Throwable $e) {
// 其他异常处理(如系统错误)
if (YAF_ENVIRON === 'product') {
echo '服务器异常,请稍后重试';
} else {
var_dump($e->getMessage());
}
}
✅ 测试:访问任意不存在的路由(如 /test/123),即可看到自定义的 404 页面!
四、进阶方案:Bootstrap 全局异常处理
大型项目推荐使用引导文件 (Bootstrap) 统一管理异常,这是 Yaf 官方推荐的规范写法,代码更优雅、易维护。
实现步骤
- 创建引导文件
application/Bootstrap.php:
php
运行
<?php
class Bootstrap extends Yaf_Bootstrap_Abstract
{
/**
* 注册全局异常处理
* @param Yaf_Dispatcher $dispatcher
*/
public function _initException(Yaf_Dispatcher $dispatcher)
{
// 全局异常捕获函数
set_exception_handler(function (Throwable $e) use ($dispatcher) {
// 处理404异常
if ($e instanceof Yaf_Exception_NotFound) {
http_response_code(404);
// 转发到404页面
$dispatcher->setRequest(new Yaf_Request_Simple('HTTP', 'Error', 'error'));
$dispatcher->dispatch();
return;
}
// 其他异常处理逻辑
if (YAF_ENVIRON === 'product') {
exit('系统错误');
}
var_dump($e->getMessage());
});
}
}
- 简化入口文件:无需手动写
try-catch,引导文件会自动接管异常处理:
php
运行
<?php
define('APP_PATH', dirname(__DIR__));
require APP_PATH . '/vendor/autoload.php';
$app = new Yaf_Application(APP_PATH . '/conf/application.ini');
$app->run(); // 直接运行即可
五、补充方案:路由兜底处理 404
除了异常捕获,还可以通过路由兜底实现 404:定义一个终极路由,匹配所有未被其他路由匹配的请求,直接转发到 404 页面。
在 Bootstrap.php 中添加路由配置:
php
运行
/**
* 初始化兜底路由
* @param Yaf_Dispatcher $dispatcher
*/
public function _initRoute(Yaf_Dispatcher $dispatcher)
{
$router = $dispatcher->getRouter();
// 正则路由:匹配所有请求(兜底路由,必须放在最后)
$router->addRoute('404_fallback', new Yaf_Route_Regex(
'#^(.*)$#',
[
'controller' => 'error',
'action' => 'error'
]
));
}
注意:兜底路由必须最后注册,否则会覆盖所有自定义路由!
六、关键注意事项
- 必须设置 404 状态码 一定要用
http_response_code(404),否则搜索引擎会将 404 页面判定为正常页面,影响 SEO。 - Linux 系统大小写问题 Yaf 在 Linux 下区分大小写,控制器名、视图目录名必须严格匹配(如
ErrorController对应views/error/)。 - 生产环境屏蔽报错 生产环境务必关闭
display_errors,避免泄露服务器信息。 - 布局模板兼容 如果项目使用了全局布局,在 404 动作中用
$this->_view->setLayout(false)禁用布局,保证页面纯净。
总结
Yaf 处理 404 页面的核心是捕获Yaf_Exception_NotFound异常,三种实现方案按需选择:
- 入门级:入口文件
try-catch,简单快速; - 进阶级:Bootstrap 全局异常处理,规范优雅,适合大型项目;
- 路由兜底:无异常捕获,纯路由实现,适合极简项目。
通过本文的方法,你可以快速为 Yaf 项目搭建一个美观、规范的 404 页面,完美兼顾用户体验与安全性。