Laravel多租户场景下,如何用Eloquent关联动态生成的表
Laravel多租户动态事件表的模型与关联实现
1. 动态设置Event模型的表名
给Event模型添加静态工厂方法,快速生成绑定指定账户事件表的模型实例:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Event extends Model { protected $connection = 'events_db'; protected $fillable = ['type', 'data', 'account_id']; // 根据实际业务字段调整 /** * 生成绑定指定账户事件表的模型实例 * * @param int $accountId * @return self */ public static function forAccount(int $accountId): self { $model = new self(); $model->setTable("account_{$accountId}_events"); return $model; } }
使用示例:
// 直接查询指定账户的事件 $events = Event::forAccount(1)->where('type', 'payment')->latest()->get();
2. 实现Account与Event的Eloquent关联
在Account模型中自定义关联逻辑,动态指定事件表名,返回可链式查询的Eloquent关联:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Account extends Model { // ... 其他模型代码 /** * 获取账户的所有事件 * * @return HasMany */ public function events(): HasMany { // 创建绑定当前账户事件表的Event模型实例 $eventModel = Event::forAccount($this->id); // 构建HasMany关联并绑定动态表名的模型 return $this->hasMany(get_class($eventModel), 'account_id', 'id') ->setModel($eventModel); } }
使用示例:
// 通过账户模型关联查询事件 $account = Account::find(1); // 链式添加查询条件 $recentLoginEvents = $account->events() ->where('type', 'login') ->where('created_at', '>=', now()->subWeek()) ->paginate(20); // 关联创建事件(自动填充account_id) $account->events()->create([ 'type' => 'login', 'data' => ['ip' => request()->ip()] ]);
可选优化:自定义关联类(复用场景)
如果需要在多个模型中复用动态表关联逻辑,可以创建自定义关联类:
<?php namespace App\Relations; use Illuminate\Database\Eloquent\Relations\HasMany; class HasManyDynamicTable extends HasMany { public function __construct($query, $parent, $foreignKey, $localKey, $tableName) { parent::__construct($query, $parent, $foreignKey, $localKey); // 动态设置模型表名 $this->query->getModel()->setTable($tableName); } }
修改Account模型的关联方法:
use App\Relations\HasManyDynamicTable; public function events(): HasManyDynamicTable { $tableName = "account_{$this->id}_events"; $query = Event::query(); return new HasManyDynamicTable( $query, $this, 'account_id', 'id', $tableName ); }
内容的提问来源于stack exchange,提问作者Phil Tune
相关产品推荐
相关产品推荐

