Askedio/laravel-soft-cascade

How to include a soft deleted relation in query? [question]

Closed this issue ยท 10 comments

Context

I have an /admin dashboard to control what to hide and what to show for the frontend.
My Job model's relationships:

Job -> belongsTo: Category
Job -> belongsTo: Company

In my admin/jobs/index.blade view I list the jobs with links to $job->company and $job->category, but because I soft deleted a company or category, it gives route error.

Question

How do I query for a trashed relationship so I can still see it?

I'm querying for jobs correctly, but the relationships aren't found, is there a way to include them even if soft deleted?

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\View\View
 */
public function index() : View
{
    $jobs = Job::latest()->withTrashed()->paginate(20);

    return view('admin.jobs.index')->with(compact('jobs'));
}

No rush. And thanks for this package, works great!! ๐Ÿ˜Ž

I found a solution:

public function index() : View
{
    $jobs = Job::with([
        'category' => function($category) {
            $category->withTrashed();
        },
        'company'  => function($company) {
            $company->withTrashed();
        }])
        ->latest()
        ->withTrashed()
        ->paginate(20);

    return view('admin.jobs.index')->with(compact('jobs'));
}

But would be nice if someone can suggest a better way or is this the best way?

Hi @emotality,

Your solution seems fine to me. Maybe @maguilar92 has another solution, I'll leave this open for a while to let him respond.

Thanks for using the package and I'm glad it's working well for you.

Hi @emotality and @gcphost .

It is Laravel's way of working with the deleted relations. Another thing you could do is create another relationship that picks up the delete relations. If you don't want to do it for each relation, you can create BaseModel or Trait with a magic __call method to implement it, for example:

public function __call($method, $arguments)
{
    if (!strpos($method, 'WithTrashed')) {
        return parent::__call($method, $arguments);
    }

    $originalMethod = str_replace('WithTrashed', '', $method);

    if (is_callable([$this, $originalMethod])) {
        return $this->{$originalMethod}()->withTrashed();
    }

    $className = get_called_class();

    throw new \Exception("Call to undefined method {$className}::{$method}()");
}

This code is not tested could have some error.

@gcphost What do you think about add in package a trait to create dinamyc withTrashed relationships?

I think it could be useful @maguilar92. I don't have much time to do it, so if you're game, I'm game.

Oks @gcphost , when I have time I will implement it to 5.7 branch.

@emotality We will implement it in 5.7 branch. When it's done I will tell you.

Awesome guys! Thanks ๐Ÿ˜‰

Hey @emotality, just do something like this in your relationships

public function myRelationship(){
 return $this->BelongsTo('App\MyModel')->withTrashed();
}

That's not a package issue, is how laravel works when you want lo load trash.