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

Laravel多租户(Tenancy)环境下如何将用户头像保存到存储目录?

解决Tenancy for Laravel + Jetstream Inertia租户子域名头像存储路径问题

问题原因

Jetstream 默认的头像上传逻辑使用全局本地磁盘,未适配Tenancy的租户隔离存储机制,导致租户子域名下上传时,因租户上下文未正确关联,文件被存储到了存储目录外的错误路径。

解决方案

1. 配置租户专属存储磁盘

在config/filesystems.php中添加租户专用磁盘,将存储根目录指向storage/app/tenants/{租户ID}:

'disks' => [
    // 保留原有磁盘配置...
    'tenant' => [
        'driver' => 'local',
        'root' => storage_path('app/tenants/' . (tenancy()->tenant?->id ?? '')),
        'visibility' => 'public',
    ],
],

使用tenancy()->tenant?->id避免无租户上下文时出现路径错误。

2. 修改Jetstream头像上传逻辑

找到app/Actions/Fortify/UpdateUserProfileInformation.php文件,修改updateProfilePhoto方法,指定使用tenant磁盘存储头像:

protected function updateProfilePhoto($user, $photo)
{
    tap($user->profile_photo_path, function ($previous) use ($user, $photo) {
        $user->forceFill([
            'profile_photo_path' => $photo->storePublicly(
                'profile-photos',
                ['disk' => 'tenant']
            ),
        ])->save();

        if ($previous) {
            \Illuminate\Support\Facades\Storage::disk('tenant')->delete($previous);
        }
    });
}

修改后,租户用户的头像会自动存储到对应租户的专属目录下。

3. 配置头像访问路径(可选)

若需通过URL直接访问头像,可选择以下两种方式:

  • 动态符号链接:在租户创建时生成对应目录的符号链接到public/storage/tenants,可在租户模型的Observer中添加:
public function created(\App\Models\Tenant $tenant)
{
    $targetDir = storage_path('app/tenants/' . $tenant->id);
    $linkDir = public_path('storage/tenants/' . $tenant->id);

    if (!file_exists($linkDir) && file_exists($targetDir)) {
        symlink($targetDir, $linkDir);
    }
}
  • 路由代理访问:添加路由直接读取存储文件,避免符号链接维护:
// routes/tenant.php
Route::get('/storage/{path}', function ($path) {
    $filePath = storage_path('app/tenants/' . tenant('id') . '/' . $path);
    if (!file_exists($filePath)) {
        abort(404);
    }
    return response()->file($filePath);
})->where('path', '.*')->middleware('auth');

4. 确保租户上下文正确初始化

检查租户路由组是否正确应用Tenancy中间件,确保上传请求时能获取到租户ID:

// routes/tenant.php
Route::middleware([
    'web',
    \Stancl\Tenancy\Middleware\InitializeTenancyByDomain::class,
    \Stancl\Tenancy\Middleware\PreventAccessFromCentralDomains::class,
])->group(function () {
    // 包含Jetstream的用户设置路由
    require base_path('routes/jetstream.php');
});

完成以上配置后,租户子域名下的头像会正确存储到storage/app/tenants/{租户ID}/profile-photos目录中。

内容的提问来源于stack exchange,提问作者Leslie Joe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:24:30