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
相关产品推荐
相关产品推荐

