RESTful API различные ответы, основанные на пользовательских ролях - PullRequest
3 голосов
/ 28 июня 2019

Я использую 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
     }

, поэтому мой вопрос в том, каков наилучший подход для достижения того, чего я хочу?

Ответы [ 5 ]

1 голос
/ 29 июня 2019

У меня сам был похожий вопрос некоторое время назад, и я нашел странное решение, чтобы избежать блока if / else.

Допущения

Я предположил существование вспомогательного метода вМодель пользователя называется isNot($role), чтобы проверить, совпадает ли роль пользователя с данной.Это всего лишь пример, чтобы дать представление о проверке, но вы должны реализовать условие так, как вам нравится.

Второе предположение, которое я сделал, состоит в том, что у каждого заказа есть поле user_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();

Наконец, чтобы лучшеконтролировать то, что отправляется обратно в качестве ответа. Я использую Ресурс API Laravel (и я действительно предлагаю вам сделать это, если вам нужно настроить ответы).

ПРИМЕЧАНИЕ: Код миграцииУ него есть синтаксические и / или логические ошибки, так как это было просто редактирование на лету из рабочего кода, и оно не было проверено, но оно должно дать общее представление о правильной реализации.

1 голос
/ 28 июня 2019

Почему бы не использовать оператор if?

Вы можете сделать область действия на модели, но тогда у вас все равно будет if.

А как насчет этого?

if ($user->role == admin) {    
    Order::all();
} else if ($user->role == normal_user) {
   $user->orders()->get();
}

Или сделайте его встроенным, если

$user->role == admin ? Order::all() : $user->orders()->get();

IMO, лучшая практика здесь заключается в создании другого Admin / OrderController.php

Затем с помощью промежуточного программного обеспечения проверьте роль пользователя и перенаправьте его на контроллеры администратора.

Поскольку вы, вероятно, также захотите обновить и удалить, или другие функции, доступные только администратору

0 голосов
/ 30 июня 2019

Такая конечная точка API REST обычно представляет собой поиск, допускающий несколько фильтров, сортировку и разбиение на страницы. Если это так, то вполне нормально применять различные значения по умолчанию для фильтров, а также ограничивать фильтры ролями.

Я бы автоматически применил фильтр user = currentUser для отсутствующей роли администратора и вернул бы запрещенное, если пользователь без роли администратора пытается применить фильтр пользователя для другого пользователя.

При таком подходе вы также даете администраторам функциональность для поиска предложений конкретного пользователя, и вам нужен только один поисковый API для использования контроллером.

0 голосов
/ 28 июня 2019

Вы можете создать область видимости в классе Order ... Например, у вас есть поле user_id в Order для обнаружения пользователя

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
  }
}
0 голосов
/ 28 июня 2019

было бы лучше включить 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())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...