搜尋

首頁  >  問答  >  主體

如何在同一模型的 Laravel 資源上使用集合

我們目前正在 codotto.com 中開發一項功能,使用者可以在其中對 IT 聚會發表評論。每個評論都可以有一個答案。我們只允許一級深層答案,例如:

- Comment 1
  - Answer to comment 1
  - Answer to comment 1
- Comment 2
  - Answer to comment 2
  - Answer to comment 2

我有以下資料庫結構:

// meetup_messages
- id
- user_id
- meetup_id
- meetup_message_id (nullable) -> comments that do not answer will have this set to nullable

在我的模型中,我將 answers 定義為 HasMany 關係:

class MeetupMessage extends Model
{
  // ...

  public function answers(): HasMany
  {
      return $this->hasMany(self::class, 'meetup_message_id');
  }
}

然後在我的控制器上,我收到所有沒有答案的評論:

public function index(
        IndexMeetupMessageRequest $request,
        Meetup $meetup,
        MeetupMessageService $meetupMessageService
    ): MeetupMessageCollection
    {
        $meetupMessages = MeetupMessage::with([
            'user',
            // 'answers' => function ($query) {
            //   $query->limit(3);
            // }
            'answers'
        ])
            ->whereNull('meetup_message_id')
            ->whereMeetupId($meetup->id)
            ->paginate();

        return new MeetupMessageCollection($meetupMessages);
    }

然後在我的 MeetupMessageCollection 上:

class MeetupMessageCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return parent::toArray($request);
    }
}

然後在我的 MeetupMessageResource 上:

<?php

namespace AppHttpResources;

use IlluminateHttpResourcesJsonJsonResource;
use IlluminateSupportCollection;

class MeetupMessageResource extends JsonResource
{
    public function toArray($request)
    {
        return collect([
            // 'answers' => new MeetupMessageCollection($this->whenLoaded('answers')),
        ])
            ->when(
                is_null($this->meetup_message_id) && $this->relationLoaded('answers'),
                function (Collection $collection) {
                    $collection->put('answers', MeetupMessageCollection::collection($this->answers));
                }
            );
    }
}

但我收到以下錯誤:呼叫未定義的方法 App\Models\Meetup\MeetupMessage::mapInto()。我如何透過將 answers 傳遞給它來仍然使用 MeetupMessageCollection

P粉029327711P粉029327711331 天前445

全部回覆(1)我來回復

  • P粉696146205

    P粉6961462052024-01-03 09:05:21

    正如 @matialauriti 所指出的,你不能在 Laravel 中的集合中使用資源集合

    class MeetupMessageResource extends JsonResource
    {
      public function toArray()
      {
        return [
          'answers' => new MeetupMessageCollction($this->answers) // ❌ You can't do this
        ]
      }
    }
    

    我的解決方案是將我的資源形成拉至私有方法,並在存在 answers 時重新使用它:

    class MeetupMessageResource extends JsonResource
    {
      public function toArray($request)
      {
          return collect($this->messageToArray($this->resource))
              ->when($this->relationLoaded('user'), function (Collection $collection) {
                  $collection->put('user', $this->userToArray($this->user));
              })
              // ✅ Now I don't need to use Resources inside my API Resource class
              ->when(
                  is_null($this->meetup_message_id) && $this->relationLoaded('answers'),
                  function (Collection $collection) {
                      $answers = $this
                          ->answers
                          ->map(function (MeetupMessage $answer) {
                              return array_merge(
                                  $this->messageToArray($answer),
                                  ['user' => $this->userToArray($answer->user)]
                              );
                          });
                      $collection->put('answers', $answers);
                  }
              );
      }
    
      private function messageToArray(MeetupMessage $meetupMessage): array
      {
          return [
              'id' => $meetupMessage->id,
              'message' => Purify::config(MeetupMessageService::CONFIG_PURIFY)->clean($meetupMessage->message),
              'answersCount' => $this->whenCounted('answers'),
              'createdAt' => $meetupMessage->created_at,
          ];
      }
    }
    

    回覆
    0
  • 取消回覆