首頁  >  文章  >  php框架  >  教你Laravel自動轉換長整型雪花ID為字串

教你Laravel自動轉換長整型雪花ID為字串

藏色散人
藏色散人轉載
2020-11-03 15:06:072740瀏覽
##下上由

Laravelaravel自動轉換長字串的方式來識別雪花IDIDIDIDID幫助字串為需要的朋友。

在設計 API 時,出於安全性等因素考慮,有時需要放棄使用自增 ID,使 ID 非連續且不可猜測。通常可以使用 Hash id,UUID,雪花 ID 等來實作。

在最近的一個專案中,我嘗試使用雪花 ID。一通折騰下來發現,逼格挺高,實作也挺簡單。然而當我繼續擼起袖子與前端部分對接時,卻出現了 JS 精度丟失問題,因為存儲的 ID 是一個 unsigned bigint 型的值。 (至於為什麼會有精度遺失現象,這裡就不具體解釋了,不清楚的可以自行搜尋),本文主要介紹解決方法。

想要解決這個問題,基本原理也很簡單,就是把 ID 轉成字串再回給前端。

錯誤嘗試

一開始我想到的是使用 Laravel Eloquent 模型的模型存取器。只要給需要轉換的模型加一個 getIdAttribute,將 ID 轉成字串不就行了嘛?

如:App\Models\User 模型裡這樣寫:

/**

 * @return string

 */public function getIdAttribute(){

    return strval($this->attributes['id']);}

但事實並非如此,屬性存取器確實能讓 API 傳回給前端的 ID 變成字串。但同時也會影響關聯模型插入、修改時的結果,例如,user 關聯的了post 模型,使用$user->posts()->saveMany(…); 這種方式保存的新的posts 記錄,對應的user_id 會為空。

這也不難理解,因為模型存取器是要參與模型相關處理的,存取器將 ID 由數字轉為了字串,自然會導致資料錯亂。

正確姿勢

冷靜下來決定先認真思考再動手,查閱了官方文檔,才發現 Resource 正是我想要的。 Resource 只會影響傳回給前端的數據,我們可以透過自訂 Resource 來實現 API 傳回結果的結構、類型轉換等功能。轉換個 ID 自然也不在話下。

為了省事,我直接修改 App\Http\Resource 這個基底類別。只需要重載它的 toArray() 方法,在其中使用遞歸,對可能超出 JS 安全數值範圍的值進行轉換就可以了。大家也可以依照自己的實際情況,新建 Resource 類,如 UserResource 來處理。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class Resource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        $parentReturn = parent::toArray($request);

        foreach (array_keys($parentReturn) as $key) {
            // 为方便演示这里把所有整型字段都转成字符串
            if (is_int($parentReturn[$key])) {
                $parentReturn[$key] = strval($parentReturn[$key]);
            }

            // 关联的字段,如 $user->post,相当于递归处理
            if (is_array($parentReturn[$key])) {
                $parentReturn[$key] = new Resource($parentReturn[$key]);
            }
        }

        return $parentReturn;
    }
}

然後,在介面控制器中傳回 Resource 傳回數據,整數欄位值就會自動變成字串了。

<?php

namespace App\Http\Controllers;

use App\Http\Resources\Resource;

use App\Models\User;

use Illuminate\Http\Request;

class TestController extends Controller
{
    /**
     * @return \App\Http\Resources\Resource
     */
    public function __invoke(Request $request)
    {
        $user = User::first();
        return new Resource($user);
    }
}

結果如下圖:
Laravel 自动转换长整型雪花 ID 为字符串

#注意事項

  • 因為這種辦法使用了遍歷,而且有遞歸處理,當資料結構複雜、資料量較大時可能會對效能造成一定影響。我這裡算是比較偷懶取巧的寫法,如果對性能有追求,自定義Resource 類,然後根據特定的已知的字段名來進行轉換會比較好

  • 因為返回給前端的ID 轉為了字串,前端在進行比較判斷,特別是=== 判斷時要特別注意

#

以上是教你Laravel自動轉換長整型雪花ID為字串的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除