我自己本地肯定是没这一类问题的,中午的时候学妹说接口500了,我一看,还真他娘的500了,response也没返回错误信息,于是我打开错误日志,发现了这么一条:
production.ERROR: RuntimeException: Unable to boot ApiServiceProvider, configure an API domain or prefix. in E:\fenke-website\vendor\dingo\api\src\Provider\DingoServiceProvider.php:82
Stack trace:
#0 E:\fenke-website\vendor\dingo\api\src\Provider\DingoServiceProvider.php(46): Dingo\Api\Provider\DingoServiceProvider->registerConfig()
当前情况是这样的:
这个时候就有点尴尬了,这种问题是程序员最不想看到的,因为是偶现,你不知道什么原因引起的,排查也无从下手,百度了好久然并卵。
那么原因是什么呢?我是一个刨根问底的人,在我的不懈努力下发现,原来这是php ts 版本会出现的问题。
这其实是php的一个已知问题(只是对于我来说是未知 :p)
问题仅仅出现在php ts版本中。下面是php手册对于putenv()函数的解释。
添加 setting 到服务器环境变量。 环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态。 设置特定的环境变量也有可能是一个潜在的安全漏洞。 safe_mode_allowed_env_vars 包含了一个以逗号分隔的前缀列表。 在安全模式下,用户可以仅能修改用该指令设定的前缀名称的指令。 默认情况下,用户仅能够修改以 PHP_ 开头的环境变量(例如 PHP_FOO=BAR)。 注意:如果此指令是空的,PHP允许用户设定任意环境变量! safe_mode_protected_env_vars 指令包含了逗号分隔的环境变量列表,使用户最终无法通过 putenv() 修改。 即使 safe_mode_allowed_env_vars 设置允许修改,这些变量也会被保护。
当PHP是线程安全的时候,putenv()和getenv()存在一个问题:如果在一个请求结束之前调用另一个请求,那么当第一个脚本完成时,它的环境变量将被重置。这对于Ajax请求来说是有问题的,或者仅仅是当用户在新标签中打开多个链接时。
下面我以laravel为例重现此问题。
首先,在路由文件中写一个请求,形如
Route::get('litblc111', function()
{
sleep(5);
return 'ENV_VALUE:' . env('API_VERSION');
});
当然要在.env文件中加入对应配置 API_VERSION=v1
ok,准备工作结束,接下来开始演示:
正常等待5s结果:
在第一次请求没有结束之前立刻再次请求的结果:
ok,这就是为什么在学妹本地环境中访问我的接口,会报错的原因,就是因为他ts版本的php没有找到env对应的值。
了解了原因,解决办法多做多样,这里我只说明一下我(laravel)开发的解决办法。
找到config / api.php
文件,大约第60行
'prefix' => env('API_PREFIX', null)
更改为
'prefix' => env('API_PREFIX', 'api')
大功告成。