簡體   English   中英

Laravel:無法訪問中間件中的資源集合

[英]Laravel: cannot access resource collection in middleware

我正在嘗試創建一個中間件,它將返回的響應包裝為我的 API 的統一 JSON 響應。 這將確保所有 API 響應具有相同的基本結構,如下所示:

{
    "success": true,
    "data": {...}
}

現在這是我目前使用的中間件:

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class ApiResponseWrapper
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /** @var Response $response */
        $response = $next($request);
        $original = $response->getOriginalContent();

        $content = [
            'success' => $response->isSuccessful(),
            'data' => $original,
        ];

        $jsonContent = json_encode($content, JsonResponse::DEFAULT_ENCODING_OPTIONS);
        $response->setContent($jsonContent);

        return $response;
    }
}

這個中間件的兩個關鍵點是:

  1. $original = $response->getOriginalContent(); line 獲取要換行的響應內容。
  2. 內容必須是字符串才能設置為新內容。 這就是為什么我使用 JSON 響應的默認編碼選項對$content進行json_encode

當我想將分頁的ResourceCollection傳遞到中間件時,就會出現問題。 控制器方法如下所示:

public function index(): AnonymousResourceCollection
{
    /** @var User $user */
    $user = auth()->user();

    return PostResource::collection($user->posts->paginate(20));
}

通常,Laravel 集合中不存在->paginate(...)方法。 這是從這里獲取的宏: gist.github.com/simonhamp/549e8821946e2c40a617c85d2cf5af5e

如果我現在點擊調用index()方法的端點,預期的輸出是這樣的:

{
    "success": true,
    "data": {
        "data": [
            <PostResource as JSON object>
        ],
        "meta": {...},
        "links": {...},
    }
}

但我實際得到的是:

{
    "success": true,
    "data": [
        <Post Model as array>
    ]
}

我想我可能需要調用一種方法來將$original (類型為Illuminate\\Support\\Collection )編碼為分頁資源集合,但我沒有找到。

其他回復都正常。 例如,在另一個控制器方法上,我只返回一個數組或字符串,它們按預期包裝。

有誰知道這里有什么問題?


編輯:

我還嘗試在設置$content變量之前添加它:

if (method_exists($original, 'toArray')) {
    $original = $original->toArray();
}

它導致ResourceCollections輸出相同。

在調查變量類型並查看 Laravel API 后,我發現最簡單的解決方案是檢查響應是否為JsonResponse並從中獲取呈現的分頁數據:

public function handle($request, Closure $next)
{
    /** @var Response $response */
    $response = $next($request);
    $content = [
        'success' => $response->isSuccessful(),
    ];

    if ($response instanceof JsonResponse) {
        /** @var JsonResponse $response */

        $data = $response->getData(true);

        $content = array_merge($content, $data);
    } else {
        $content['data'] = $response->getOriginalContent();
    }

    $jsonContent = json_encode($content, JsonResponse::DEFAULT_ENCODING_OPTIONS);
    $response->setContent($jsonContent);

    return $response;
}

這導致了我的用例的預期響應:

{
    "success": true,
    "data": [
        <PostResource as JSON object>
    ],
    "meta": {...},
    "links": {...},
}

另請注意,我最初在包裝data鍵中指定了datametalinks鍵。 我發現上面的結果有點漂亮,因為我繞過了雙包裝data

我希望這會幫助任何遇到這個問題的人!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM