Laravel与Adonis中单一User表按角色关联不同模型的可行性
单表按角色拆分关联模型的实现方案(Laravel & Adonis)
Laravel 实现方式
完全可以实现,推荐两种常用方案:
1. 带角色约束的关联方法
直接在User模型中定义关联,并通过where条件限制仅对应角色的用户能获取关联数据:
// app/Models/User.php public function posts() { // 仅consumer角色用户能获取关联的Post return $this->hasMany(Post::class)->where('role', 'consumer'); } public function pricing() { // 仅maker角色用户能获取关联的Pricing return $this->hasOne(Pricing::class)->where('role', 'maker'); }
使用时,非对应角色的用户调用关联方法会返回空集合,业务层可根据实际场景做判断处理。
2. 单表继承(STI)
创建对应角色的子类模型,继承User并添加全局作用域自动过滤角色,关联逻辑写在子类中,更符合单一职责:
// app/Models/Consumer.php class Consumer extends User { protected $table = 'users'; protected static function booted() { static::addGlobalScope('role', function ($query) { $query->where('role', 'consumer'); }); } public function posts() { return $this->hasMany(Post::class); } } // app/Models/Maker.php class Maker extends User { protected $table = 'users'; protected static function booted() { static::addGlobalScope('role', function ($query) { $query->where('role', 'maker'); }); } public function pricing() { return $this->hasOne(Pricing::class); } }
使用时直接通过子类查询:Consumer::find($id)->posts 或 Maker::find($id)->pricing,逻辑更清晰。
AdonisJS 实现方式
同样支持该需求,以下是两种可行方案:
1. 动态条件关联
在User模型中定义动态关联方法,根据当前用户角色返回对应关联或空结果:
// app/Models/User.ts import { BaseModel, column, hasMany, hasOne, HasMany, HasOne } from '@ioc:Adonis/Lucid/Orm' import Post from 'App/Models/Post' import Pricing from 'App/Models/Pricing' export default class User extends BaseModel { @column() public role: string public async getPosts() { if (this.role !== 'consumer') { return [] } return this.related('posts').query() } public async getPricing() { if (this.role !== 'maker') { return null } return this.related('pricing').query().first() } @hasMany(() => Post) public posts: HasMany<typeof Post> @hasOne(() => Pricing) public pricing: HasOne<typeof Pricing> }
也可以直接在关联的查询回调中添加条件,限制仅对应角色能获取关联数据。
2. 单表继承(STI)
创建角色子类模型,添加全局作用域过滤角色,关联逻辑封装在子类中:
// app/Models/Consumer.ts import User from './User' import { scope, hasMany, HasMany } from '@ioc:Adonis/Lucid/Orm' import Post from './Post' export default class Consumer extends User { public static consumerScope = scope((query) => { query.where('role', 'consumer') }) protected static booted() { super.booted() this.addGlobalScope(this.consumerScope) } @hasMany(() => Post) public posts: HasMany<typeof Post> } // app/Models/Maker.ts import User from './User' import { scope, hasOne, HasOne } from '@ioc:Adonis/Lucid/Orm' import Pricing from './Pricing' export default class Maker extends User { public static makerScope = scope((query) => { query.where('role', 'maker') }) protected static booted() { super.booted() this.addGlobalScope(this.makerScope) } @hasOne(() => Pricing) public pricing: HasOne<typeof Pricing> }
使用时通过子类查询:await Consumer.query().first().then(user => user.posts),自动过滤角色并返回对应关联数据。
内容的提问来源于stack exchange,提问作者toy toy
相关产品推荐
相关产品推荐

