You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel多租户包资源跨租户不同步问题及解决记录

Laravel多租户资源跨分支同步问题解决记录

问题场景

基于Tenancy For Laravel的multi db方案开发SaaS系统,超级管理员可创建分支(租户),各分支拥有独立的客户、文档等资源。当前遇到的问题:

  • 在某分支创建客户时,客户能正常同步到当前分支数据库与中央数据库,中间表tenant_customers也生成对应记录
  • 但该客户未同步到其他分支数据库,不符合“所有分支共享该客户”的预期

相关代码片段

中央端Customer模型

class Customer extends AbstractCustomer implements SyncMaster
{
    use CentralConnection, ResourceSyncing;

    public function tenants(): BelongsToMany
    {
        return $this->belongsToMany(Branch::class, 'tenant_customers', 'global_id', 'tenant_id', 'global_id')
            ->using(TenantPivot::class);
    }
    
    public function getTenantModelName(): string
    {
        return TenantCustomer::class;
    }

    public function getGlobalIdentifierKey()
    {
        return $this->getAttribute($this->getGlobalIdentifierKeyName());
    }

    public function getGlobalIdentifierKeyName(): string
    {
        return 'global_id';
    }

    public function getCentralModelName(): string
    {
        return static::class;
    }

    public function getSyncedAttributeNames(): array
    {
        return $this->fillable;
    }
}

租户端Customer模型

class Customer extends AbstractCustomer implements Syncable
{
    use ResourceSyncing;

    public function getGlobalIdentifierKey()
    {
        return $this->getAttribute($this->getGlobalIdentifierKeyName());
    }

    public function getGlobalIdentifierKeyName(): string
    {
        return 'global_id';
    }

    public function getCentralModelName(): string
    {
        return CentralCustomer::class;
    }

    public function getSyncedAttributeNames(): array
    {
        return $this->fillable;
    }
}

客户控制器store方法

public function store(StoreCustomerRequest $request)
{
    $validatedData = $request->validated();

    $customer = new Customer($validatedData);
    $customer->save();

    return redirect()->route('tenant.customers.create', tenant('id'))
        ->with([
            'success', 'New Customer has been added!'
         ]);
}

排查与解决过程

最初参考官方示例尝试手动关联资源到租户,使用类似$customer->tenants()->attach($tenant)的代码时,出现错误:Attempt to read property prepare on null。

最终找到两个关键解决点:

  1. 正确的租户关联方式:必须手动将客户关联到所有租户,正确代码如下:
// 获取系统内所有租户的ID数组
$tenantIds = Tenant::pluck('id')->toArray();
// 同步关联当前客户到所有租户
$customer->tenants()->sync($tenantIds);
  1. 会话配置导致的同步异常:跨分支同步失败的根源在于会话存储驱动,将config/session.php中的driver配置项从database修改为file后,资源跨分支同步功能恢复正常。

内容的提问来源于stack exchange,提问作者Huzaifa Qayyum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:08:18