Search code examples
phplaravel

timestamps() relationship in Model returns true in Laravel Resource class


I have a Scene Model which has a one to many relationship with Timestamp Model

  public function timestamps(): HasMany
    {
        return $this->hasMany(Timestamp::class);
    }

when i access this relationship in my Resource File (SceneResource)

class SceneResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'quest_id' => $this->quest_id,
            'description' => $this->description,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
            'background' => $this->backgroundImage->image_url ?? null,
            'timestamps' => $this->timestamps
        ];
    }
}

$this->timestamps return true instead of a collection. I am suspecting a naming conflict with laravel timestamps

Note: relation is properly loaded

if (!is_null($user) && ($user->role === "admin" || $user->role === "super_admin" || $user->role === "user_manager")) {
            $quests = Quest::with(['uploadedImage', 'previewList', 'scenes' => ['timestamps']]);
        } else {
            $quests = Quest::with(['uploadedImage', 'previewList', 'scenes' => ['timestamps']])
                ->where('description', "!=", null)
                ->where('mission_brief', "!=", null)
                ->where('description', "!=", "")
                ->where('mission_brief', "!=", "");
        }

        try {
            return response()->json([
                'status_code' => Response::HTTP_OK,
                'message' => 'Quest returned successfully',
                'data' => (new QuestResourceCollection($quests->orderByDesc('created_at')->paginate(12)))->resolve(),
            ], Response::HTTP_OK);
        } catch (Exception $e) {

ignore if unwarranted if statement 😁

I have tried renaming the method which works but just curious if there is a way around this without refactoring


Solution

  • No, there is no way around it without changing the name of the relationship.

    Eloquent Models use the HasTimestamps trait, which adds a public $timestamps property to the model itself. (public $timestamps = true;)

    Relationship properties are implemented using the PHP magic __get() method. This method is only called when you attempt to access a property on the class that doesn't exist. Your problem is that the timestamps property does exist, so you'll get the value of that property, and you will not be able to use the magic relationship property.

    If you want to be able to use the relationship property, you'll have to rename your relationship. If you don't want to rename the relationship, you'll always need to access the relationship through the relationship method, or by using getAttribute() manually:

    'timestamps' => $this->getAttribute('timestamps'),