当急切加载时,当关系中的外键为空且因此与任何相关记录不匹配时,是否可以避免执行额外查询?在我的示例中,我有Product
和User
。
Product
归User
所有,但也可以选择由User
进行编辑。所以我的模型看起来像这样:
class Product extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
public function editor()
{
return $this->belongsTo(User::class, 'editor_id');
}
}
未对产品进行修改时,editor_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
我猜这是因为无法保证此方法返回Relation
个对象。
由于
答案 0 :(得分:1)
我通过创建一个实现所需方法的新Relation
子类来解决这个问题,但在实际获得结果时只返回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');
}
}
它有点难看,而且你会重复自己很多,所以如果我在不止一个地方使用它,我可能会创建Model
的子类,然后创建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');
}
答案 1 :(得分:0)
Laravel Docs
选择
时查询关系访问模型的记录时,您可能希望根据关系的存在来限制结果。
$posts= Post::has('editor')->get();
您还可以指定运算符和计数:
$posts = Post::has('editor', '>=', 3)->get();