简介
本指南面向DouPHP应用“无法启动”或“启动异常”的常见场景,围绕引导流程、环境检查、配置校验、权限与日志定位等维度,提供可操作的排障步骤。重点覆盖:
- PHP版本与扩展兼容性
- 数据库连接与存储目录权限
- 配置文件错误(含安装锁、站点调试开关)
- 自动加载与命名空间映射异常
- 前台/后台/API入口差异
- 调试模式启用与错误堆栈获取
- Web服务器与PHP错误日志分析方法
项目结构
DouPHP采用多入口+统一引导的设计:根入口负责路由预处理与异常兜底;core/bootstrap.php完成基础常量、路径、自动加载与容器初始化;各端(front/admin/api)通过各自的Init类执行端侧初始化;SiteBootstrap负责从数据库装配站点配置并写入Config门面。
graph TB
A["index.php<br/>前台入口"] --> B["core/bootstrap.php<br/>基础引导"]
B --> C["core/autoload.php<br/>自动加载"]
B --> D["容器/请求单例注册"]
A --> E["front/init/Init.php::boot()<br/>前台初始化"]
E --> F["core/init/InitTrait.php<br/>共享初始化步骤"]
E --> G["core/bootstrap/SiteBootstrap.php<br/>站点配置装配"]
E --> H["core/foundation/exception/SiteDebugExceptionRenderer.php<br/>调试渲染"]
图示来源
- index.php:14-75
- core/bootstrap.php:15-180
- front/init/Init.php:63-89
- core/init/InitTrait.php:535-602
- core/bootstrap/SiteBootstrap.php:44-68
- core/foundation/exception/SiteDebugExceptionRenderer.php:40-105
核心组件
- 前台入口 index.php:设置路由委托、解析语言前缀、调用 Init::boot、分发路由、统一异常处理与响应发送。
- 基础引导 core/bootstrap.php:定义ROOT_PATH/CONFIG_PATH/STORAGE_PATH等常量、检测未安装状态、载入config/config.php、注册自动加载、注入容器与Request单例、注册HTTP助手与事件注册器。
- 前台初始化 front/init/Init.php:会话与时区、根URL计算、语言解析、视图引擎装配、模块与语言包加载、站点关闭检测、支付对账兜底触发。
- 共享初始化 core/init/InitTrait.php:错误报告级别、时区、安全配置、文件系统/AI配置、核心对象实例化(DB/Session/Csrf/Xss/Url/RouteIdValidator)、日志运行时开关、全局异常与致命错误兜底、诊断级错误去重限流落盘。
- 站点配置装配 core/bootstrap/SiteBootstrap.php:从数据库装配site/param到Config门面。
- 调试渲染 core/foundation/exception/SiteDebugExceptionRenderer.php:判断是否开启调试、JSON-like请求识别、Whoops全局HTML渲染、API JSON 500输出。
架构总览
下图展示一次前台请求从入口到初始化的关键阶段,以及异常在何处被捕获与渲染。
sequenceDiagram
participant U as "浏览器"
participant I as "index.php"
participant B as "core/bootstrap.php"
participant R as "路由/请求"
participant F as "front/init/Init.php"
participant T as "InitTrait.php"
participant S as "SiteBootstrap.php"
participant X as "SiteDebugExceptionRenderer.php"
U->>I : 发起HTTP请求
I->>B : require bootstrap
B-->>I : 常量/自动加载/容器就绪
I->>R : setDelegate(Request/Router)
I->>F : boot(routeInfo)
F->>T : startSession/setTimezone/computeRootUrl
F->>S : loadSite/loadParameter
F->>F : setupViewEngine/loadLanguageAndModules
F-->>I : 初始化完成
I->>R : dispatch()
R-->>U : Response
Note over I,X : 若发生异常,由入口try/catch与X统一渲染
图示来源
- index.php:14-75
- core/bootstrap.php:15-180
- front/init/Init.php:63-89
- core/init/InitTrait.php:535-602
- core/bootstrap/SiteBootstrap.php:44-68
- core/foundation/exception/SiteDebugExceptionRenderer.php:40-105
详细组件分析
引导程序执行流程与关键检查点
- PHP版本与协议常量:bootstrap中强制要求PHP版本不低于指定阈值,并基于$_SERVER推导HTTPS与IS_HTTPS。
- 未安装跳转:若storage/install.lock不存在且非install路径,将跳转到安装入口。
- 配置文件加载:读取config/config.php,定义数据库变量与系统常量(如DOU_CHARSET、ADMIN_DIR、API_DIR、MINIPROGRAM_DIR、DOU_APP_KEY、DOU_DEBUG)。
- 自动加载与别名:注册autoload与短名别名,便于后续使用DB/Session/Storage等门面。
- 容器与请求单例:提前绑定DelegatingRouter与Request单例,确保Init::boot之前可用。
- 前台Init::boot:会话与时区、根URL、语言解析、视图引擎、语言与模块加载、站点关闭检测、支付对账兜底。
- 共享初始化InitTrait:错误报告级别、安全配置、文件系统/AI配置、核心对象实例化、日志运行时开关、全局异常与致命错误兜底、诊断级错误去重限流。
- 站点配置装配:SiteBootstrap从数据库装配site/param到Config门面,供后续逻辑使用。
异常处理与调试模式
- 入口异常捕获:index.php对HttpResponseException、RedirectException、DomainException及通用Exception/Throwable进行捕获,按是否JSON请求与是否已boot决定响应形式。
- 调试渲染:SiteDebugExceptionRenderer根据DOU_DEBUG或site.debug决定是否开启调试;对JSON-like请求返回结构化500;对HTML请求尝试Whoops渲染或降级为纯HTML堆栈。
- 日志运行时:InitTrait在initLogRuntime中根据site.log_runtime与各端开关决定是否写data/log/{front|admin|api}/,并在非debug下接管notice/warning/deprecated/strict,去重限流后落盘。
flowchart TD
Start(["异常发生"]) --> CheckBoot{"是否已完成Init?"}
CheckBoot --> |是| JsonReq{"是否JSON请求?"}
CheckBoot --> |否| JsonReq
JsonReq --> |是| Api500["发送API 500(含堆栈片段)"]
JsonReq --> |否| DebugOn{"是否开启调试?"}
DebugOn --> |是| Whoops["Whoops HTML调试页或降级HTML"]
DebugOn --> |否| MsgPage["message提示或page_wrong"]
Api500 --> End(["结束"])
Whoops --> End
MsgPage --> End
图示来源
- index.php:38-75
- core/foundation/exception/SiteDebugExceptionRenderer.php:40-105
- core/foundation/exception/SiteDebugExceptionRenderer.php:149-188
- core/foundation/exception/SiteDebugExceptionRenderer.php:220-235
自动加载与命名空间映射
- 插件类:Dou\Plugin*优先解析plugin/<name>/src或plugin/<name>下的类文件。
- Core类:Dou\Core*按目录映射到core/对应子目录。
- 端侧类:Dou\Admin/Front/Api按层(Init/Lib/Middleware/Http/Controller/Model/Service/Request/Facade/Foundation/Contract)映射到对应端目录。
- 模块类:Dou\Core\Module*按已安装模块清单动态构建ClassMap。
- Vendor类:Dou\Vendor*映射到core/library/{package}/...。
- 兜底:按命名空间片段映射到core同名目录。
依赖关系分析
- 入口依赖:index.php依赖core/bootstrap.php与前端路由/请求解析。
- 引导依赖:core/bootstrap.php依赖config/config.php、core/autoload.php,并注册容器与Request单例。
- 初始化依赖:front/init/Init.php依赖InitTrait、SiteBootstrap、视图引擎与模块服务。
- 调试依赖:SiteDebugExceptionRenderer依赖Config与可选Whoops库。
graph LR
Index["index.php"] --> Boot["core/bootstrap.php"]
Boot --> Autoload["core/autoload.php"]
Boot --> Config["config/config.php"]
Index --> FrontInit["front/init/Init.php"]
FrontInit --> Trait["core/init/InitTrait.php"]
FrontInit --> SiteBoot["core/bootstrap/SiteBootstrap.php"]
FrontInit --> Debug["SiteDebugExceptionRenderer.php"]
图示来源
- index.php:14-75
- core/bootstrap.php:15-180
- front/init/Init.php:63-89
- core/init/InitTrait.php:535-602
- core/bootstrap/SiteBootstrap.php:44-68
- core/foundation/exception/SiteDebugExceptionRenderer.php:40-105
性能注意事项
- 启动阶段仅做必要初始化:数据库连接、会话、语言与模块按需加载,避免在Init中执行重型任务。
- 日志运行时:生产环境建议关闭site.log_runtime或降低最小日志级别,减少磁盘IO。
- 模板编译目录:确保storage/cache/template/front可写,避免重复创建目录开销。
- 自动加载:合理组织命名空间与文件路径,减少autoload解析分支。
故障排查指南
一、PHP版本与扩展兼容
- 现象:直接终止并提示版本过低。
- 原因:bootstrap中对PHP版本进行严格比较,低于最低版本即中止。
- 解决:升级至要求的最低版本及以上;确认mysqli扩展可用(框架内部会关闭mysqli严格报告以兼容旧行为)。
- 验证:访问任意页面,观察是否仍报版本错误。
二、未安装导致跳转
- 现象:访问首页被重定向到安装程序。
- 原因:storage/install.lock不存在且当前请求不是install路径。
- 解决:完成安装流程或在storage目录下创建install.lock(通常由安装脚本生成)。
- 验证:再次访问首页应进入正常流程。
三、配置文件错误
- 现象:启动时报错或行为异常(如数据库连接失败、路径错误、调试模式不生效)。
- 关键点:
- config/config.php定义了数据库连接、字符集、目录常量与应用密钥与调试标志。
- DOU_DEBUG可来自define或site.debug,优先级前者更高。
- 解决:核对数据库主机/用户名/密码/表前缀;确认DOU_DEBUG值符合预期;检查ADMIN_DIR、API_DIR、MINIPROGRAM_DIR是否与目录一致。
- 验证:临时开启调试模式,查看具体错误信息。
四、存储目录与权限
- 现象:模板编译失败、日志无法写入、安装锁无法创建。
- 关键点:
- storage/用于运行时数据(缓存、日志、安装锁等)。
- 前台视图引擎会在storage/cache/template/front下创建编译目录。
- 解决:确保storage及其子目录对Web运行用户可写;清理损坏的编译缓存后重试。
- 验证:访问页面后检查storage/cache/template/front是否生成编译文件;检查storage/log/{front|admin|api}/是否写入日志。
五、数据库连接失败
- 现象:启动早期抛出连接错误或查询失败。
- 关键点:
- 数据库配置来源于config/config.php中的$dbhost/$dbuser/$dbpass/$dbname/$prefix。
- 核心对象实例化时会创建Connection并注入容器。
- 解决:修正数据库连接参数;确认网络可达与账号权限;必要时调整端口或Socket方式。
- 验证:在调试模式下查看具体错误信息与堆栈;检查data/log/front/是否有相关错误记录。
六、自动加载失败
- 现象:Class not found或命名空间解析异常。
- 关键点:
- autoload.php按规则解析Dou\Plugin、Dou\Core、端侧类、模块类、Dou\Vendor与兜底路径。
- 插件类支持plugin/<name>/src与plugin/<name>两种结构。
- 解决:检查类文件路径是否符合约定;确认模块清单正确;修复命名空间与文件名大小写。
- 验证:触发对应类加载,观察是否成功require_once。
七、会话与安全配置
- 现象:Cookie无效、跨站请求被拒、代理IP识别错误。
- 关键点:
- startSession在InitTrait中设置session cookie参数(httponly、samesite、secure),并根据IS_HTTPS决定是否secure。
- loadSecurityConfig在instantiateCommonFactories之前读取security.php并设置可信代理与主机名单。
- 解决:检查security.php的session块与trusted_proxies/trusted_hosts;确认反向代理配置正确。
- 验证:观察请求头与Cookie行为;检查审计服务记录的IP是否正确。
八、站点关闭与强制HTTPS
- 现象:访问被重定向到https或显示站点关闭提示。
- 关键点:
- loadLanguageAndModules中若开启ssl且当前非HTTPS,则301重定向。
- checkSiteClosed中若site.site_closed为真,直接输出关闭提示并退出。
- 解决:检查site.ssl与site.site_closed配置;确认反向代理正确传递HTTPS信息。
- 验证:访问页面观察重定向或关闭提示。
九、调试模式与错误堆栈
- 开启方式:
- define('DOU_DEBUG', true)在config/config.php中(应急优先)。
- 或通过数据库site.debug项控制。
- 效果:
- HTML请求:尝试Whoops渲染或降级为包含类名、消息、文件行号与堆栈的HTML。
- JSON请求:返回标准API 500响应,errors字段包含异常类、文件、行号与堆栈片段。
- 日志:
- site.log_runtime开启时,data/log/{front|admin|api}/写入运行时日志;非debug下notice/warning/deprecated/strict会被去重限流后落盘。
- 验证:
- 打开调试后访问页面,观察是否出现调试页或API 500;检查日志目录是否产生新文件。
十、Web服务器与PHP错误日志
- 位置:
- PHP错误日志:由PHP配置决定(php.ini的error_log),或在调试模式下由Whoops/调试页直接输出。
- 应用运行时日志:data/log/{front|admin|api}/,由InitTrait管理。
- 技巧:
- 在生产环境保持site.log_runtime开启但最小日志级别为WARNING,避免大量诊断噪音。
- 结合Web服务器访问日志与错误日志交叉定位请求路径、UA、IP与时间戳。
- 验证:
- 触发一次错误,检查data/log/front/是否新增日志;同时查看PHP错误日志是否记录。
十一、环境配置验证与自动检测
- 快速自检清单:
- PHP版本是否满足最低要求。
- storage/目录可写,install.lock存在与否符合预期。
- config/config.php中数据库参数正确。
- DOU_DEBUG按预期设置。
- security.php中trusted_proxies/trusted_hosts与反向代理一致。
- 视图编译目录storage/cache/template/front可写。
- 自动检测工具:
- 可利用调试模式与日志运行时功能作为“软检测”,观察错误与日志输出即可推断环境问题。
- 对于数据库连接,可在调试模式下查看具体错误信息;如需硬检测,可编写简单脚本调用PDO/mysqli测试连通性(不在本项目范围内)。
十二、典型故障案例与解决步骤
-
案例A:访问首页跳转到安装程序
- 现象:首次部署后首页重定向到install/index.php。
- 原因:storage/install.lock不存在。
- 解决:完成安装流程或创建install.lock。
- 验证:刷新首页进入正常流程。
- 参考:core/bootstrap.php:42-57
-
案例B:白屏或500错误,无详细信息
- 现象:页面空白或返回500,无堆栈。
- 原因:调试模式关闭或未开启Whoops。
- 解决:在config/config.php中开启DOU_DEBUG;检查site.debug;确认Whoops可用。
- 验证:重新访问,出现调试页或API 500 errors字段。
- 参考:core/foundation/exception/SiteDebugExceptionRenderer.php:40-105
-
案例C:数据库连接失败
- 现象:启动报错或查询失败。
- 原因:config/config.php中数据库参数错误或网络不可达。
- 解决:修正$dbhost/$dbuser/$dbpass/$dbname/$prefix;检查防火墙与账号权限。
- 验证:调试模式下查看错误信息;检查data/log/front/日志。
- 参考:config/config.php:15-28
- 参考:core/init/InitTrait.php:293-344
-
案例D:模板编译失败
- 现象:页面报错或样式缺失。
- 原因:storage/cache/template/front不可写或缓存损坏。
- 解决:赋予目录可写权限;清理缓存后重试。
- 验证:检查目录是否生成编译文件。
- 参考:front/init/Init.php:442-466
-
案例E:强制HTTPS重定向
- 现象:http访问被301到https。
- 原因:site.ssl开启且当前非HTTPS。
- 解决:确认反向代理正确传递HTTPS;或关闭site.ssl。
- 验证:访问http与https均能正常跳转或访问。
- 参考:front/init/Init.php:276-292
结论
DouPHP的启动流程清晰分层:入口负责路由与异常兜底,bootstrap负责环境与自动加载,Init负责端侧初始化,SiteBootstrap装配站点配置。大多数启动问题集中在PHP版本、安装锁、配置文件、存储目录权限、数据库连接与调试模式设置。通过启用调试模式与查看运行时日志,可以快速定位错误源并修复。建议在开发环境开启调试与详细日志,在生产环境保持最小日志级别并确保日志轮转与权限正确。
附录
- 常用检查点速查:
- PHP版本与扩展:mysqli可用,版本满足最低要求。
- 安装状态:storage/install.lock存在与否符合预期。
- 配置文件:config/config.php中数据库参数与DOU_DEBUG正确。
- 存储目录:storage/及其子目录可写。
- 安全配置:security.php中trusted_proxies/trusted_hosts与反向代理一致。
- 视图编译:storage/cache/template/front可写。
- 日志:data/log/{front|admin|api}/可写且有新日志。
- 调试模式开关优先级:
- define('DOU_DEBUG', true)优先于site.debug。
- JSON-like请求返回结构化500;HTML请求尝试Whoops渲染。