Search code examples
laraveleloquentsoft-delete

How to retrieve soft delete parent in laravel with eloquent


I have a model named Work.

A work can be either a Project, a Task or a Subtask. It is saved in a workable_type column representing the class.

A work has a getParentAttribute which retrieve the parent of a task or a subtask :

 public function getParentAttribute()
    {
        if ($this->isTask()) {
            $task = $this->workable;
            $project = $task->project;
            return $project->work;
        }
        if ($this->isSubtask()) {
            $subtask = $this->workable;
            $task = $subtask->task;
            return $task->work;
        }
    }

And has a getArborescenceAttribute :

    public function getArborescenceAttribute()
    {
        if ($this->isProject()) {
            return null;
        }

        if ($this->isTask()) {
            return ["project" => [
                "id" => $this->parent->id,
                "workable_id" => $this->parent->workable_id,
                "name" => $this->parent->name
            ]];
        }

        if ($this->isSubtask()) {
            return [
                "task" => [
                    "id" => $this->parent->id,
                    "workable_id" => $this->parent->workable_id,
                    "name" => $this->parent->name
                ],
                "project" => [
                    "id" => $this->parent->parent->id,
                    "workable_id" => $this->parent->parent->workable_id,
                    "name" => $this->parent->parent->name
                ]
            ];
        }
    }

The problem I have is that I can't retrieve the soft deleted models in the arborescence because $this->parent returns null

I tried $this->parent->withTrashed()->id, but it returns me that id is not an attribute of Builder.

How would you do ?


Solution

  • You need to call the withTrashed() method on your parent's relation(s).
    If I understand your relations right, in your getParentAttribute() method, the parent that may have been trashed is $project or $task.
    So it should be :

    public function getParentAttribute()
    {
        if ($this->isTask()) {
            $task = $this->workable;
            $project = $task->project()->withTrashed()->get();
            return $project->work;
        }
        if ($this->isSubtask()) {
            $subtask = $this->workable;
            $task = $subtask->task()->withTrashed()->get();
            return $task->work;
        }
    }
    

    You might need to call it on your workable relation too : $this->workable()->withTrashed()->get();

    If you need you could have 2 methods getParentAttribute() only for not trashed and getParentWithTrashedAttribute() for everything.