为啥我的资源不返回所有具有“with”方法的元数据?

Posted

技术标签:

【中文标题】为啥我的资源不返回所有具有“with”方法的元数据?【英文标题】:Why my resource do not return all meta data having "with" method?为什么我的资源不返回所有具有“with”方法的元数据? 【发布时间】:2021-09-09 13:31:34 【问题描述】:

在 lumen 8 应用程序中,我使用资源并在此处阅读 https://laravel.com/docs/8.x/eloquent-resources

我尝试使用“with”方法,因为我想向任何请求添加一些元数据,但我没有 返回数据中的此元数据:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use App\Models\Page As PageModel;
use App\Http\Resources\User as UserResource;


    class Page extends JsonResource
    
        public function toArray($request)
        
            return [
                'id' => $this->id,
                'title' => $this->title,
                ...
                'created_at' => $this->created_at,
            ];
        
    
        public function with($request)
        
            \Log::info( '-1 unction with ::' . print_r( 1, true  ) ); // I DO NOT SEE THIS LOGGINHG line
    
            return [
                'meta' => [
                    'version'=>getAppVersion()
                ]
            ];
        
    
    

在引用的文档中,资源声明与 ResourceCollection 有点不同:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection

    public function toArray($request)
    
        return parent::toArray($request);
    

    public function with($request)
    
        return [
            'meta' => [
                'key' => 'value',
            ],
        ];
    

这可能是问题吗?如何修复我的资源以获取所有元数据?

更新块: UserCollection - 即集合https://laravel.com/docs/8.x/eloquent-resources 我的收藏是 Page,我在控制器中使用它:

namespace App\Http\Controllers;

use Carbon\Carbon;
use App\Models\Page;
use Illuminate\Http\Request;
use App\Http\Resources\Page as PageResource;
use Config;
use App\Http\Requests\PageRequest;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Validator;

class PageController extends Controller

    public function index()
    
        $pages = Page
            ...
            ->get();

        return $this->sendOkResponse(PageResource::collection($pages), '');

    

sendOkResponse 定义在 Http/Controllers/Controller.php 中:

class Controller extends BaseController

    protected $requestData;

    public function __construct()
    
        $request           = request();
        $this->requestData = $request->all();
    

    public function sendOkResponse($responseResult, $message)
    
        $response = [
            'success' => true,
            'data'    => $responseResult,
            'message' => $message,
        ];
        return response()->json($response, HTTP_RESPONSE_OK);
    

我想 PageResource 在 PageController 控制器索引方法退出时被销毁...

更新区块#2: 经过一些测试,我发现如果返回集合,资源方法“with”不起作用 我需要在控制器中使用 ->additional,例如:

return (PageResource::collection($pages)) 
->additional([
    'meta' => [
        'version' => getAppVersion()
    ]
]);

但是在我返回 sinopgle 元素(ex store 方法)的情况下

return (new PageResource($page));

“with”方法可以正常工作。

这不包括使用像 sendOkResponse 这样的包装器。 是唯一正确的方法吗?

提前致谢!

【问题讨论】:

您在哪里以及如何实例化此 UserCollection 以及传递了什么参数?实例化后是否存在集合? 我在更新块中提供了附加信息。这就是你所要求的吗? 是的,所以您在日志文件中看到了\Log::info() 数据?您的 PageCollection 是否包含 调用 sendOkResponse() 之前的数据? 1) 不,我看不到 Log::info 的数据,因此不调用“with”方法。 2) 不,如在行 return $this->sendOkResponse(PageResource::collection($pages), '');我两者都用,没有任何新方法。我有没有以某种方式用 new 初始化 PageResource? 能否在PageControllerindex函数中添加dd(PageResource::collection(Page::all()));的结果截图? 【参考方案1】:

Laravel 资源旨在直接从控制器的操作方法返回,而不是作为表示 JSON 的关联数组的一部分。

当使用sendOkResponse 方法包装您的响应时,不会直接从该方法返回资源,因此会在您的资源上调用toArray。正在忽略您资源上的 with 方法。

尝试直接从控制器的方法返回资源。在构造资源时使用additional 方法来传递响应中的额外属性。请参阅:https://laravel.com/docs/8.x/eloquent-resources#adding-meta-data-when-constructing-resources。

如果您可以控制 API 合约,我建议您将它们更改为完全省略 success,这可以从 HTTP 状态代码中获得。

【讨论】:

我将我的类定义为:class Page extends JsonResource with command : php artisan make:resource PageResource 但是在你的链接中使用了 UserCollection,我想它是用命令 php artisan make:resource User 创建的——集合我更喜欢使用基于 JsonResource 的资源,因为有些请求 1 个对象,而不是集合。有关系吗? 请看更新的区块#2

以上是关于为啥我的资源不返回所有具有“with”方法的元数据?的主要内容,如果未能解决你的问题,请参考以下文章

为啥具有对象基础的元类会引发元类冲突?

为啥一个类具有它的元类的属性?

为啥我的用户数据没有使用资源控制器中的 show 方法传递到页面视图?

WITH 子句可以在不使用 Select 语句的情况下具有硬编码值吗?

为啥不调用具有 const 引用返回值的重载方法?

为啥在编译时不检查 lambda 返回类型?