laravel - 使用带有 MorpMany 关系的 toHasOne 宏
问题描述
我有多个利用 HasRetirements 特征类的模型类。两种模型都使用 MorphMany 关系来定位每个模型的关联退休表模型。在 HasRetirements trait 类中,我还有一个 isRetired() 方法和一个 currentRetirement() 方法。这些方法如下所示。
我遇到了一个可以链接到 Eloquent 关系的宏,以便您可以检索单个记录。宏 toHasOne() 通过 hasMany 关系利用模型关系,但是我的问题是这也可以用于 morphMany 关系,因为它是多态的。
https://scotch.io/tutorials/understanding-and-using-laravel-eloquent-macros
public function currentRetirement()
{
return $this->retirements()->whereNull('ended_at')->latest()->toHasOne();
}
public function isRetired()
{
return $this->retirements()->whereNull('ended_at')->exists();
}
解决方案
使用 Laravel 5.5,您可以注册一个宏,从BelongsToMany
关系中返回派生类。如果您不打算在其他任何地方使用它,这个派生类也可以是匿名类。在派生类中,您需要覆盖该match
方法并将单个对象作为关系返回或null
以其他方式返回
BelongsToMany::macro('asSingleEntity', function() {
return new class(
$this->related->newQuery(),
$this->parent,
$this->table,
$this->foreignPivotKey,
$this->relatedPivotKey,
$this->parentKey,
$this->relatedKey,
$this->relationName) extends BelongsToMany {
/**
* Match the eagerly loaded results to their parents.
*
* @param array $models
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, Collection $results, $relation)
{
$dictionary = $this->buildDictionary($results);
// Once we have an array dictionary of child objects we can easily match the
// children back to their parent using the dictionary and the keys on the
// the parent models. Then we will return the hydrated models back out.
foreach ($models as $model) {
if (isset($dictionary[$key = $model->{$this->parentKey}])) {
$model->setRelation(
// $relation, $this->related->newCollection($dictionary[$key]) // original code
$relation, array_first($dictionary[$key])
);
} else {
$model->setRelation($relation, null);
}
}
return $models;
}
};
});
然后,您可以简单地在模型中使用它。
return $this
->belongsToMany(\App\Models\Entity::class, 'pivot_table_name')
->asSingleEntity();
推荐阅读
- c - 带有 EVP_PKEY_decrypt() 的段错误
- javascript - 控制台日志区域有额外的行
- json - 需要以角度 8 传递动态 json 数据
- python - Ubuntu,致命错误:Python.h:没有这样的文件或目录#include
- java - 如何以编程方式将 fab 图标色调设置为 null?
- javascript - this.parentNode 不是 javascript 中的函数?
- c++ - 我的代码和巴比伦之间的动画差异,为什么?
- javascript - 将解析的对象转换为类实例
- vue.js - Vue Create - 在“...2”“标准版本”附近解析时 JSON 输入意外结束
- laravel - 手动触发 Stripe 订阅 webhook