背景描述
- 项目使用的是laravel5.3,公司新招了个学妹写前端,于是我觉得应该改变一下项目结构,我负责写api,她渲染界面,使用ajax动态无刷新,前后端分离。
- 我的环境是php7.1 nts apache mysql fastcgi运行模式;学妹的是wamp php ts 版本。
问题产生
我自己本地肯定是没这一类问题的,中午的时候学妹说接口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,准备工作结束,接下来开始演示:
- 首先在我本地环境演示(nts),访问这个路由,在sleep(5)没有结束之前再次访问,无论我怎么访问,他都会正常输出v1。

- 接下来在学妹的电脑上(ts)演示,同样的操作细节,结果却返回空!
正常等待5s结果:
在第一次请求没有结束之前立刻再次请求的结果:
ok,这就是为什么在学妹本地环境中访问我的接口,会报错的原因,就是因为他ts版本的php没有找到env对应的值。
解决办法
了解了原因,解决办法多做多样,这里我只说明一下我(laravel)开发的解决办法。
- 1 他不是找不到值么,好的,我给他个默认值:
找到config / api.php文件,大约第60行
'prefix' => env('API_PREFIX', null)
更改为
'prefix' => env('API_PREFIX', 'api')
大功告成。
- 2 虽然
getenv()不行了,但是$ _ENV和$ _SERVER还是可以正常使用的。
参见
- 5.0 Environment variables sometimes return null #8191
- Use phpdotenv methods instead of getenv/putenv #7425
- "Unable to boot ApiServiceProvider, configure an API domain or prefix" with API_PREFIX defined #1074
本文由 litblc 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Aug 10, 2018 at 01:02 pm


Hello, I enjoy reading all of your article. I wanted to write a little comment to support you.
seo查询www.09seo.cn