这篇文章给大家分享的是有关Laravel自动转换长整型雪花ID为字符串的示例的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
在设计API时,出于安全性等因素考虑,有时需要放弃使用自增ID,使ID非连续且不可猜测。通常可以使用散列ID、UUID、雪花ID等来实现。
在最近的一个项目中,我尝试使用雪花ID。一通折腾下来发现,逼格挺高,实现也挺简单,然而当我继续撸起袖子与前端部分对接时,却出现了JS精度丢失问题,因为存储的ID是一个无符号长整型数字型的值。(至于为什么会有精度丢失现象,这里就不具体解释了,不清楚的可以自行搜索),本文主要介绍解决办法。
想要解决这问题,基本原理也很简单,就是把ID转成字符串再返回给前端。
错误尝试
一开始我想到的是使用Laravel雄辩的模型的模型访问器。只要给需要转换的模型加一个getIdAttribute,将ID转成字符串不就行了嘛?
如:应用\ \用户模型模型里这样写:
/* * ,* @return 字符串 ,*/public function  getIdAttribute () { ,,,return strval ($ this→属性(& # 39;ID # 39;]);}
但事实并非如此,属性访问器确实能让API返回给前端变的ID为字符串。但同时也会影响关联模型插入,修改时的结果,例如,用户关联的了后模型,使用$ user→帖子()→saveMany (…);这种方式保存的新职位的记录,对应的user_id会为空。
这也不难理解,因为模型访问器是要参与模型相关处理的,访问器将ID由数字转为了字符串,自然会导致数据错乱。
正确姿势
冷静下来决定先认真思考再动的手,查阅了官方文档,才发现资源正是我想要的.Resource只会影响返回给前端的数据,我们可以通过自定义资源来实现API返回结果的结构,类型转换等功能。转换个ID自然也不在话下。
为了省的事,我直接修改程序\ Http \资源这个基类,只需要重载它的toArray()方法,在其中使用递归,对可能超出JS安全数值范围的值进行转换就可以了。大家也可以根据自己的实际情况,新建资源类,如UserResource来处理。
& lt; php ? namespace App \ Http \资源; use 阐明\ Http \ \ Json \ JsonResource资源; class Resource  extends JsonResource { ,,,/* * ,,,,*,Transform 从而resource into an 数组。 ,,,, ,,,,*,@param \照亮\ Http \ Request 美元请求 ,,,, ,,,,*,@return 数组 ,,,*/,,,public function toArray(请求) ,,,{ ,,,,,,,parentReturn 美元;=,父:toArray($请求); ,,,,,,,foreach (中的(parentReturn美元),as 美元键),{ ,,,,,,,,,,,//,为方便演示这里把所有整型字段都转成字符串 ,,,,,,,,,,,if (is_int ($ parentReturn [$ key])), { ,,,,,,,,,,,,,,,parentReturn美元(美元关键),=,strval ($ parentReturn [$ key]); ,,,,,,,,,,,} ,,,,,,,,,,,//,关联的字段,如,用户→美元,相当于递归处理 ,,,,,,,,,,,if (is_array ($ parentReturn [$ key])), { ,,,,,,,,,,,,,,,parentReturn美元(美元关键),=,new 资源($ parentReturn [$ key]); ,,,,,,,,,,,} ,,,,,,,} ,,,,,,,return parentReturn美元; ,,,} }
然后,在接口控制器中返回资源返回数据,整型字段值就会自动变为字符串了。
& lt; php ? namespace 应用\ Http \控制器; use \ App \ Http \资源资源; use 应用\ \用户模型; use 照亮\ Http \请求; class TestController  extends 控制器 { ,,,/* * ,,,,*,@return \ \ App \ Http \资源资源 ,,,*/,,,public function __invoke (Request $请求) ,,,{ ,,,,,,,user 美元;=,用户:第(); ,,,,,,,return new 资源(用户); ,,,} }
结果如下图:
注意事项
- <李>
因为这种办法使用了遍历,而且有递归处理,当数据结构复杂,数据量较大时可能会对性能造成一定影响。我这里算是比较偷懒取巧的写法,如果对性能有追求,自定义资源类,然后根据特定的已知的字段名来进行转换会比较好