Laravel关系避免了外键为空的查询

Laravel关系避免了外键为空的查询,laravel,orm,laravel-5,eloquent,Laravel,Orm,Laravel 5,Eloquent,当急加载时,当关系中的外键为null,因此与任何相关记录都不匹配时,是否可以避免执行额外的查询?在我的示例中,我有一个产品和用户 产品属于用户,但也可以由用户编辑。因此,我的模型如下所示: class Product extends Model { public function user() { return $this->belongsTo(User::class); } public function editor() {

当急加载时,当关系中的外键为null,因此与任何相关记录都不匹配时,是否可以避免执行额外的查询?在我的示例中,我有一个
产品
用户

产品
属于
用户
,但也可以由
用户
编辑。因此,我的模型如下所示:

class Product extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function editor()
    {
        return $this->belongsTo(User::class, 'editor_id');
    }
}
未编辑产品时,其
编辑器id
属性为
NULL

如果我不急于加载,我知道我可以做如下事情:

$product = Product::find(1);
if (!is_null($product->editor_id)) {
    // Load the relation
}
但是,这对我来说不是一个选项,我希望在急切加载时避免运行额外的、不必要的查询:

Query: select * from `users` where `users`.`id` in (?)
Bindings: [0]
我想知道是否可能有类似的事情发生

public function editor()
{
    if (!is_null($this->editor_id)) {
        return $this->belongsTo(User::class, 'editor_id');
    }
}
执行上述操作时,我会出现以下错误:

Call to a member function addEagerConstraints() on a non-object
我猜这是因为不能保证该方法返回
关系
对象

谢谢

Laravel文档

选择时查询关系

访问模型的记录时,您可能希望根据关系的存在限制结果

 $posts= Post::has('editor')->get();
您还可以指定运算符和计数:

  $posts = Post::has('editor', '>=', 3)->get();

我通过创建一个新的
关系
子类解决了这个问题,该子类实现了所需的方法,但在实际获得结果时只返回null:

namespace My\App;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\Relation;

class NullRelation extends Relation {

    public function __construct() {}

    public function addConstraints() {}

    public function addEagerConstraints(array $models) {}

    public function initRelation(array $models, $relation) {}

    public function match(array $models, Collection $results, $relation) {
        return [];
    }

    public function getResults() {
        return null;
    }

}
然后,在关系方法中,您可以检查null并返回
NullRelation
的实例:

public function editor() {
    if ($this->editor_id === null) {
        return new NullRelation();
    } else {
        return $this->belongsTo(User::class, 'editor_id');
    }
}
它有点难看,而且你会重复很多次,所以如果我在多个地方使用它,我可能会创建
模型
的子类,然后创建
belongsTo
hasOne
方法的版本,并在那里执行检查:

public function belongsToIfNotNull($related, $foreignKey = null, $otherKey = null, $relation = null) {
    if ($this->$foreignKey === null) {
        return new NullRelation();
    } else {
        return parent::belongsTo($related, $foreignKey, $otherKey, $relation);
    }
}
最后,在继承新子类的模式中,关系方法变得简单

public function editor() {
    return $this->belongsToIfNotNull(User::class, 'editor_id');
}

这只是你文章中的一个输入错误,还是你真的运行了这个代码?因为
USer::class
应该是
USer::class
。好吧,你不能这样做,你的关系必须返回一些东西,否则,Laravel尝试调用nulluse上的一个方法whereHas condition,也许它会帮到你。嗨,伙计们,谢谢你们的回答@是的,我知道它需要返回一些东西,这就是我出错的原因@Imtiaz Pabel-在这种情况下,我将如何使用
Where has
?你能举个例子吗?+1我真的很喜欢你的方法。我甚至认为只要简单地重写模型类上的默认关系方法,就可以做到这一点,因为我发现额外的查询完全是多余的。