2

I am creating a project where users can study with flash cards. I have an API from which users can retrieve decks of cards. Users who are not authenticated can still retrieve decks, but their learning progress is not stored in the database.

I would like for authenticated user to receive extra data in the response when retrieving flash cards from the API. More specifically, each card should have an extra 'study_at' field containing a date for when they should study that card next.

The 'study_at' date is stored in a pivot table called 'card_user'.

I have tried to modify the toArray() method on the Card model, but I don't know if that was the way to go.

This is the API endpoint:

Route::get('/decks', 'DecksController@index');

DecksController

class DecksController extends Controller
{
    public function index()
    {
        $decks = Deck::all();

        return new DeckCollection($decks);
    }

DeckCollection

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

DeckResource

class DeckResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'cards' => new CardCollection($this->cards),
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

CardCollection

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

CardResource

Here is where I want to include the 'study_at' date

class CardResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'front' => $this->front,
            'back' => $this->back,
            // Include 'study_at' date here
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

This is the response that I would like an authenticated user to recieve:

{
    "id": 1,
    "name": "Coffee Break French",
    "cards": [
        {
            "id": 1,
            "front": "Good morning",
            "back": "Bonjour",
            "study_at": "2019-05-26T15:00:00.000000Z"
            "created_at": "2019-04-14T21:04:05.000000Z",
            "updated_at": "2019-04-14T21:04:05.000000Z"
        },
        {
            "id": 2,
            "front": "Good afternoon",
            "back": "Bonne après-midi",
            "study_at": "2019-05-26T15:00:00.000000Z"
            "created_at": "2019-04-14T21:04:21.000000Z",
            "updated_at": "2019-04-14T21:04:21.000000Z"
        },
        {
            "id": 3,
            "front": "My name is John",
            "back": "Je m'appelle John",
            "study_at": "2019-05-26T15:00:00.000000Z"
            "created_at": "2019-04-14T21:04:37.000000Z",
            "updated_at": "2019-04-14T21:04:37.000000Z"
        }
    ],
    "created_at": "2019-04-14T21:03:38.000000Z",
    "updated_at": "2019-04-14T21:03:38.000000Z"
}

2 Answers 2

4

To include an attribute only under certain condition you should use conditional attributes:

class CardResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'front' => $this->front,
            'back' => $this->back,
            // Include 'study_at' date here
            'study_at' => $this->when(auth()->user(), $this->study_at), // Retrieve your value through eloquent relation
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

That is exactly what I wanted, although I'm getting auth()->user() to null. Auth is configured with Passport and valid Authorization header is passed. Any ideas?
Solved it. The problem was that I had configured the route outside of the auth:api middleware. Moving it inside the route group with that middleware solved the problem.
0

You may define a relationship with Laravel Eloquent:

class Card extends Model
{
   public function userCard() {
     // your relationship
   }
}
class CardResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'front' => $this->front,
            'back' => $this->back,
            'study_at' => $this->userCard,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

See: https://laravel.com/docs/5.8/eloquent-relationships

2 Comments

That is not the issue, there is already a relationship set up between cards and users.
@soomro yes sorry i missed the part I would like for authenticated user

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.