Askedio / laravel-soft-cascade

Cascade Delete & Restore when using Laravel SoftDeletes
https://medium.com/asked-io/cascading-softdeletes-with-laravel-5-a1a9335a5b4d
MIT License
705 stars 63 forks source link

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

Closed emotality closed 5 years ago

emotality commented 6 years ago

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!! 😎

emotality commented 6 years ago

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?

gcphost commented 6 years ago

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.

maguilar92 commented 6 years ago

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.

maguilar92 commented 6 years ago

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

gcphost commented 6 years ago

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

maguilar92 commented 6 years ago

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

maguilar92 commented 6 years ago

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

emotality commented 6 years ago

Awesome guys! Thanks 😉

cacpmw commented 5 years ago

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

public function myRelationship(){
 return $this->BelongsTo('App\MyModel')->withTrashed();
}
maguilar92 commented 5 years ago

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