Laravel关系避免了外键为空的查询
当急加载时,当关系中的外键为null,因此与任何相关记录都不匹配时,是否可以避免执行额外的查询?在我的示例中,我有一个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() {
产品
和用户
产品
属于用户
,但也可以由用户
编辑。因此,我的模型如下所示:
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我真的很喜欢你的方法。我甚至认为只要简单地重写模型类上的默认关系方法,就可以做到这一点,因为我发现额外的查询完全是多余的。