Comment utiliser les collections sur les ressources Laravel sur le même modèle
P粉029327711
P粉029327711 2024-01-02 10:53:45
0
1
433

Nous développons actuellement une fonctionnalité sur codotto.com où les utilisateurs peuvent laisser des commentaires sur les rencontres informatiques. Chaque commentaire peut avoir une réponse. Nous n'autorisons qu'un seul niveau de réponses approfondies, par exemple :

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

J'ai la structure de base de données suivante :

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

Dans mon modèle je vais answers 定义为 HasMany la relation :

class MeetupMessage extends Model
{
  // ...

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

Puis sur ma manette je reçois tous les commentaires sans réponses :

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);
    }

Puis sur mon MeetupMessageCollection :

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

Puis sur mon 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));
                }
            );
    }
}

Mais j'obtiens l'erreur suivante : Appel à la méthode non définie AppModelsMeetupMeetupMessage::mapInto(). Comment puis-je continuer à utiliser 调用未定义的方法 AppModelsMeetupMeetupMessage::mapInto()。我如何通过将 answers 传递给它来仍然使用 MeetupMessageCollection en lui transmettant des réponses ?

P粉029327711
P粉029327711

répondre à tous(1)
P粉696146205

Comme @matialauriti l'a souligné, vous ne pouvez pas utiliser de collections de ressources au sein des collections dans Laravel

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

Ma solution consistait à extraire mon formulaire de ressources dans une méthode privée et à le réutiliser lorsque answers est présent :

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,
      ];
  }
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal