我正在使用Laravel作为我的PHP框架。约定将index show store ...
函数放入控制器。
我有2种类型的用户(管理员和普通用户)。假设有一个Order
(餐厅)模型,我想为其控制器实现index
功能。
一个用户可以有多个订单。
我需要的是该功能:
- 如果管理员正在调用此API:返回所有订单
- 如果普通用户正在调用此API:仅返回该用户拥有的订单
我搜索了,但什么也找不到(我不知道要搜索什么)。
一旦执行以下操作,我就不喜欢它,因为它看起来像是聚集了两个不同的功能:
if ($user->role == admin) {
// fetch all orders
} else if ($user->role == normal_user) {
// just find user orders
}
所以我的问题是实现我想要的最好的方法是什么?
答案 0 :(得分:1)
为什么不使用if语句?
您可以在模型上创建范围,但是仍然有一个if。
那呢?
UPDATE Purchase p JOIN
(SELECT aw.PurchaseID, SUM(aw.Price) as total_price
FROM Artwork aw
WHERE aw.PurchaseID = 'D4758'
GROUP BY aw.PurchaseID
) aw
ON p.PurchaseID = aw.PurchaseID
SET p.Total = aw.total_price;
或者将其设为内联
if ($user->role == admin) {
Order::all();
} else if ($user->role == normal_user) {
$user->orders()->get();
}
IMO的最佳做法是制作一个不同的Admin / OrderController.php
然后使用中间件检查wat,确定用户的角色,然后将其重定向到管理控制器。
由于您可能还希望更新和删除或仅由管理员使用的其他功能
答案 1 :(得分:1)
不久前,我自己也遇到了类似的问题,最后提出了一个奇怪的解决方案,以避免该if / else阻塞。
我假设用户模型中存在一个名为isNot($role)
的辅助方法,以验证用户的角色是否匹配给定的角色。
这只是给出检查想法的一个示例,但是您应该根据需要实现条件。
我做出的第二个假设是,每个订单都有一个user_id
字段,该字段将通过其ID(用户和订单之间的FK为1:N)来引用该订单的所有者。
public function index(Request $request)
{
$orders = Order::query()
->when($request->user()->isNot('admin'), function ($query) use ($request) {
return $request->user()->orders();
// Or return $query->where('user_id', $request->user()->id);
})
->paginate();
return OrderResource::collection($orders);
}
when
方法是这里的关键。基本上,您可以这样称呼它:when($value, $callback)
,如果$value
是false
,则不会执行该回调,否则它将执行。
因此,例如,如果用户不是管理员,则最终将执行以下查询:
Order::paginate();
这样可以分页获取所有订单(请注意,您可以将paginate
与get
交换。
否则,将执行回调,您将在paginate
上执行$request->user()->orders();
方法(像方法一样被调用的顺序仍然是查询生成器对象,因此可以在其上调用paginate)。
查询将是:
$request->user()->orders()->paginate();
如果您选择在回调中选择第二种解决方案,则基本上可以在主范围中添加一个where条件(对订单的user_id进行过滤),以仅获取用户的订单。
查询将是:
Order::query()->where('user_id', $request->user()->id)->paginate();
最后,为了更好地控制作为响应发送回的内容,我使用了Laravel's API Resource(如果需要自定义响应,我也建议您也这样做)。
注意::该代码可能存在语法和/或逻辑错误,因为它只是对生产代码进行即时编辑,并且尚未经过测试,但应该给出一个总体思路以获得正确的实施方式。
答案 2 :(得分:0)
最好将if / else包含在您的订单模式中,如下所示:
class Order extends Model {
....
static function fetchFor (User $user) : Collection
{
return $user->isAdmin() ? self::all() : self::where("user_id",$user->id);
}
}
然后您可以在控制器上调用此方法
public function index()
{
return view('your-view')->with('orders',Order::fetchFor(Auth::user())->get())
}
答案 3 :(得分:0)
您可以在Order类中创建范围... 例如,您在Order中有一个user_id字段,用于检测用户
class Order
{
...
public function scopeByRole($query)
{
if (!Auth::user()->isAdmin())
$query = $query->where('user_id', Auth::user()->id);
return $query;
}
}
在您的控制器中,只需获取所有具有范围的订单:
$orders = Order::byRole()->get();
按角色返回订单
此外,您还需要在类User中具有检测角色的功能,例如
class User
{
public function isAdmin()
{
// you logic which return true or false
}
}
答案 4 :(得分:0)
这种REST API端点通常是允许多个过滤器,排序和分页的搜索。如果是这样,完全可以为过滤器应用不同的默认值,并将过滤器限制为角色。
如果没有管理员角色的用户尝试为其他用户应用用户过滤器,我将自动为缺少的管理员角色应用过滤器user = currentUser并返回禁止。
通过这种方法,您还可以为管理员提供搜索特定用户的要约的功能,并且控制器只需要使用一个搜索api。