使用Laravel7如何限制用户仅可创建1个店铺、关闭对应Create CRUD访问权限
这个需求完全可实现,基于你使用的Laravel 7、MySQL技术栈,最优方案需要从数据库兜底、后端核心校验、前端体验优化三层做限制,既避免恶意绕过前端操作的安全问题,也能保证普通用户的使用体验。
1 数据库层约束(兜底防护,避免脏数据)
这是最底层的安全保障,就算后端逻辑出现漏洞,也能从数据库层面阻止同用户生成多条店铺记录:
- 确保你的
shops表存在关联用户的user_id字段,给该字段添加唯一索引 - 执行的迁移代码如下:
Schema::table('shops', function (Blueprint $table) { $table->unique('user_id'); });
2 后端逻辑层校验(核心控制层)
2.1 先定义用户和店铺的关联
首先在User模型中添加一对一关联方法,后续所有校验都基于这个关联判断:
// app/User.php public function shop() { return $this->hasOne(Shop::class); }
2.2 用中间件拦截店铺创建请求
创建专门的中间件,统一拦截所有和店铺创建相关的请求:
- 生成中间件命令:
php artisan make:middleware HasNoShop - 中间件逻辑代码:
// app/Http/Middleware/HasNoShop.php public function handle($request, Closure $next) { if ($request->user()->shop) { // 已有店铺的用户直接跳转到店铺编辑页,也可以返回403错误 return redirect()->route('shops.edit', $request->user()->shop)->with('error', '你已拥有店铺,无需重复创建'); } return $next($request); }
- 把中间件注册到
app/Http/Kernel.php的$routeMiddleware数组:
protected $routeMiddleware = [ // 其他原有中间件 'has.no.shop' => \App\Http\Middleware\HasNoShop::class, ];
- 给店铺创建相关的路由绑定该中间件:
// routes/web.php // 单独给创建接口加中间件 Route::get('shops/create', 'ShopController@create')->middleware('has.no.shop')->name('shops.create'); Route::post('shops', 'ShopController@store')->middleware('has.no.shop')->name('shops.store'); // 其他店铺CRUD路由不需要加这个中间件,用户可以正常编辑自己的店铺 Route::resource('shops', 'ShopController')->except(['create', 'store']);
2.3 用Policy限制店铺操作权限
为了确保用户只能修改自己的店铺,推荐用Laravel原生的Policy策略做权限控制:
- 生成策略命令:
php artisan make:policy ShopPolicy --model=Shop - 策略中添加编辑权限校验逻辑:
// app/Policies/ShopPolicy.php public function update(User $user, Shop $shop) { return $user->id === $shop->user_id; }
- 把策略注册到
app/Providers/AuthServiceProvider.php的$policies数组,之后在ShopController的构造方法中添加全局授权即可:
// app/Http/Controllers/ShopController.php public function __construct() { $this->authorizeResource(Shop::class, 'shop'); }
3 前端视图层控制(用户体验优化)
在前端视图中根据用户的店铺存在状态,控制按钮的显示逻辑,避免用户点进创建页再被拦截的割裂感:
@if(auth()->user()->shop) <a href="{{ route('shops.edit', auth()->user()->shop) }}">编辑我的店铺</a> @else <a href="{{ route('shops.create') }}">创建店铺</a> @endif
内容的提问来源于stack exchange,提问作者BeaQ
相关产品推荐
相关产品推荐

