自定义一对一、一对多(多态)关系的实现
当表type类型为int时,需要使用到多态关系,类似以下结构
posts
id - integer
name - string
users
id - integer
name - string
images
id - integer
url - string
type_id - integer
type - int
首先按官方文档定义关系
Relation::morphMap([
1 => Posts:class,
0 => Users:class
]);
再images模型中定义
public static function booted()
{
Relation::morphMap([
1 => Posts:class,
0 => Users:class
]);
}
public function imageable()
{
return $this->morphTo(__FUNCTION__, 'type', 'type_id');
}
//该定义为了预加载with实现
public function getTypeAttribute($value)
{
return [
1 => Posts:class,
0 => Users:class
][$value];
}
当然也可以按官方提供的定义App\Providers\AppServiceProvider类的 boot方法内(除非你的系统只有一个地方使用到0,1 type类型)
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
Relation::morphMap([
1 => Posts:class,
0 => Users:class
]);
}
当type类型是顺序的0,1,2…,切记不要按顺序定义数组,否则框架中会按索引数组映射关系。框架的映射逻辑如下(src/Illuminate/Database/Eloquent/Relations/Relation.php 446行):
protected static function buildMorphMapFromModels(array $models = null)
{
if (is_null($models) || Arr::isAssoc($models)) {
return $models;
}
return array_combine(array_map(function ($model) {
return (new $model)->getTable();
}, $models), $models);
}
完成以上配置后就可以使用自定义多态模型的查询
(Images::find(1))->imageable;
(Images::with(['imageable']))->take(10)->get();
Images::with(['imageable'=>function (MorphTo $morphTo) {
$morphTo->constrain( [
Posts::class => function (Builder $query) {
$query->select(['id',...]);
},
Users::class => function (Builder $query) {
$query->select('id',...);
},])
->morphWith([
Posts::class => ['xxx:id,title'],
])])->whereHasMorph('imageable',[Posts::class])->take(10)->get();
本作品采用《CC 协议》,转载必须注明作者和本文链接