如何在Laravel 4中查询和过滤软删除的Eloquent模型

3
使用来自https://github.com/snipe/laravel4-starter的Laravel 4.1起始套件,我有2个模型:类别和兴趣。两者都可以软删除。我希望索引视图根据用户的愿望显示3个不同的列表:“显示全部”,“显示已删除”和“显示未删除”。 一切都很好,直到我在它们之间添加了HasMany / BelongsTo关系。 模型:
class Category extends Elegant
{
    protected $softDelete = true;

    public function interests()
    {
        return $this->hasMany('Interest');
    }
}

class Interest extends Elegant
{
    protected $softDelete = true;

    public function category()
    {
        return $this->belongsTo('Category');
    }
}

现在,当视图调用属于已软删除的分类的兴趣$interest->category->name时,会出现ErrorException: Trying to get property of non-object。我怀疑这是因为$interest->category为空,因为它已被软删除而没有被加载。

控制器:

class InterestsController extends AdminController
{

    public function getIndex()
    {
        $showDisabled = Utility::GetShowDisabled();

        switch ($showDisabled) {
            case 'only':
                // How to load *only* soft-deleted Interest with their categories
                // even if the category has been soft-deleted?
                $interests = Interest::onlyTrashed()->orderBy('name')->paginate(10);
                break;
            case 'with':
                // How to load *all* Interests with their categories
                // even if the category has been soft-deleted?
                $interests = Interest::withTrashed()->orderBy('name')->paginate(10);
                break;

            default:
                // How to load *only* *NON-soft-delted* Interests with their categories
                // even if the category has been soft-deleted?
                $interests = Interest::orderBy('name')->paginate(10);
                break;
        }

        return View::make('backend/interests/index', compact('interests', 'showDisabled'));
    }

请看switch语句中每个区块的问题。我怀疑解决方案可能涉及某种急切加载,但即使经过了一些非常激烈的谷歌搜索和试验,正确的咒语仍然使我困惑...

额外加分:如何加载所有未被软删除的兴趣,并过滤掉具有已软删除类别的兴趣?

谢谢。

3个回答

8

预加载类别:

Interest::with(['category' => function ($q) {
   $q->withTrashed();
}])->onlyTrashed()->get();
// the same for other cases

具有类别(未删除)的兴趣:

Interest::with('category')->has('category')->get();

你的回答第二部分是正确的,所以你会得到额外的积分。不幸的是,我的主要问题仍然存在。$interests = Interest::with('category')->onlyTrashed()->get(); 加载了所有被删除的兴趣,并预加载它们的类别。问题在于它只预加载了未删除的类别。因此视图仍然无法正常显示。我希望即使这些类别已被删除,也能加载兴趣并预加载类别。在这里,onlyTrashed() 应用于查询中的 Interest 部分。 - CodeMonkey
请重新表达你的问题,因为这不是你所问的。无论如何,请检查编辑内容以了解如何在渴望加载查询中应用任何内容。请注意,您仍然可以拥有没有相关类别(无论删除与否)的“兴趣”,因此基本上您仍然要在该关系上检查“null”。 - Jarek Tkaczyk
谢谢,这正是我想要的。出于好奇,你会怎么表达这个问题? - CodeMonkey

0

感谢Jarek Tkaczyk的提示。 以下是我最终使用的代码片段,供其他人参考:

    $query = Interest::with(array('category' => function ($subQuery) {
        $subQuery->withTrashed();
    }));

    switch ($showDisabled) {
        case 'only':
            $query->onlyTrashed();
            break;
        case 'with':
            $query->withTrashed();
            break;
        case 'without':
            break;

        default:
            $showDisabled = "activeonly";
            $query->has('category');
            break;
    }

    $searchTerms = explode(' ', $searchQ);
    $query->where( function ($subQuery) use ($searchTerms) {
        $termCnt = 0;
        foreach($searchTerms as $term)
        {
            (0 == $termCnt)
                ? $subQuery->Where('name', 'LIKE', '%'. $term .'%')
                : $subQuery->orWhere('name', 'LIKE', '%'. $term .'%');
            $termCnt++;
        }
    });

    $interests = $query->orderBy($sortByCol, $order)->paginate(10);

0

改为:

SoftDeleted = true;

使用:

use SoftDeletes;

这对我来说很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接