【发布时间】:2019-12-20 18:16:28
【问题描述】:
我正在尝试创建一个中间件,它将返回的响应包装成我的 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;
}
}
这个中间件的两个关键点是:
-
$original = $response->getOriginalContent();行获取要换行的响应内容。 - 内容必须是字符串才能设置为新内容。这就是为什么我
json_encode$content使用 JSON 响应的默认编码选项。
当我想将分页的ResourceCollection 传递到中间件时,问题就出现了。控制器方法如下所示:
public function index(): AnonymousResourceCollection
{
/** @var User $user */
$user = auth()->user();
return PostResource::collection($user->posts->paginate(20));
}
通常,->paginate(...) 方法不存在于 Laravel 集合中。这是一个取自这里的宏: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 的输出结果相同。
【问题讨论】:
-
如果你使用
'data' => $original->toArray()会发生什么? -
@FelippeDuarte 它会产生相同的输出,而不是想要的输出。
-
旁注:不要在集合上调用
->paginate,您应该能够在该关系的查询构建器上调用它:$user->posts()->paginate(20),而不需要任何宏。由于过滤和限制是在数据库级别完成的,而不是在内存对象中,这也会表现得更好 -
@mdexp 通常,你是对的。然而,就我而言,
posts实际上是一个模型访问器:Defining An Accessor。您对性能的看法可能是正确的,我一定会对此进行调查。谢谢!
标签: php json laravel resources middleware