自定义函数需显式加载且注意作用域与版本兼容性:必须在入口文件或配置中引入common.php,调用时不用命名空间前缀,tp5.0与5.1+的json()参数不同,调试应使用halt()或日志并确保app_debug开启。

自定义函数没生效?先确认加载路径和入口顺序
TP5 的自定义函数(比如 app\common.php 里的 success()、error()、show())不会自动加载,必须显式引入。常见错误是只写了函数,却没在框架启动前 require 进来。
检查点:
-
app\common.php文件必须被thinkphp/start.php或项目入口(如public/index.php)之前的某处require或include; - 推荐做法:在
application\common.php中写好函数后,在application\config.php的'extra'配置项里加入'common',让框架自动加载; - 如果手动 require,请确保它出现在
require THINK_PATH . 'base.php';之后、任何控制器执行之前; - 改完
common.php后,务必清空runtime/目录,否则旧缓存可能掩盖函数未更新的问题。
调用时报“Call to undefined function”?检查命名空间和作用域
自定义函数默认属于全局命名空间,但若你在控制器方法里用了 use 声明或当前类有命名空间,就容易误以为函数需要加 \ 前缀或属于某个类。
典型错误场景:
- 在控制器中写
$this->success()—— 这是调用控制器父类的success()方法,不是你写的全局函数;应直接写success(); - 在命名空间为
app\api\controller的文件里调用show()却写成app\api\controller\show()—— 错,全局函数不走命名空间,直接show()即可; - 函数定义在
extend/下的文件中,但没在composer.json的"autoload": {"files": []}里声明,导致 Composer 自动加载失败。
函数逻辑对但返回异常?注意 json() 的参数兼容性
你写的 success()、show() 最终都调用 TP5 的 json() 辅助函数,但它在不同 TP5 小版本中参数签名不一致。
常见陷阱:
- TP5.0.x 的
json($data)不支持第二个 HTTP 状态码参数,传了会报错;TP5.1+ 才支持json($data, $code); - 如果你在
show()里写了return json($data, $httpCode);,而项目是 TP5.0.24,则必须降级为return json($data)->code($httpCode);; -
json()默认 Content-Type 是application/json,但如果响应被中间件拦截(如 CORS)、或你同时用了redirect(),会导致 headers 已发送,再调用json()报 “headers already sent” 错误。
想断点调试自定义函数?别用 debug(),改用 halt() 或日志
TP5 自带的 debug() 函数本质是 var_dump() + exit,但它在非调试模式下会被禁用,且输出格式不友好。真要调试函数内部流程,更可靠的是:
- 在函数关键位置插入
halt($var)(TP5 内置,输出并终止); - 用
trace('msg', 'debug')记录到 Trace 面板(需开启APP_DEBUG和'app_trace' => true); - 写入日志:
think\Log::record('xxx: ' . print_r($data, true), 'info');,然后查runtime/log/下对应日期文件; - 避免在
common.php顶层直接调用debug()或halt(),那会导致整个框架加载失败。
最易被忽略的一点:自定义函数的调试效果高度依赖 APP_DEBUG 是否真正生效——它不仅影响错误显示,还决定 trace()、Log::record() 等行为是否启用。哪怕函数本身语法完全正确,只要 APP_DEBUG 没在入口文件第一行硬编码开启,很多调试手段就等于没开。











