Поэтому каждый раз, когда мне нужно выполнить фильтрацию списка ресурсов в API, вот как я это делаю.
Однако, прежде чем я начну, небольшой совет относительно получения объекта Request, когда вы находитесь в методе вашего контроллера: если вы добавите Request $request
в качестве параметра для вашей функции all()
, у вас будет доступ к переменной $request там, так же, как ваш конструктор. Таким образом, полная подпись будет public function all(Request $request)
. Методы контроллера имеют ту же магическую инъекцию зависимостей, что и другие конструкторы классов в Laravel/Lumen. Кроме того, в своей функции вы всегда можете попросить функцию app()
предоставить вам объект определенного класса. Поскольку объект запроса привязан в контейнере только к «запросу», вы можете запросить полное имя класса или просто «запрос»: $request = app('request');
Итак, когда у меня есть объект запроса, внутри моего метода контроллера мне нравится проходить каждый фильтр либо как группу, либо один за другим, в зависимости от того, насколько сложным является каждый фильтр. Иногда фильтры бывают сложными, например список идентификаторов, разделенных запятыми, которые необходимо разбить на массив. Однако, если это просто строковые фильтры, я обычно выбрасываю список в массив и просматриваю его.
Вот пример функции для иллюстрации некоторых идей:
public function getIndex(Request $request)
{
//Create a User object to append WHERE clauses onto
$user = app('App\Models\User');
//Run through our simple text fields
foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
if ($request->has($field)) {
$user->where($field, $request->input($field));
}
}
//This field uses a LIKE match, handle it separately
if ($request->has('email')) {
$user->where('email', LIKE, '%' . $request->input('email') . '%');
}
//This field is a list of IDs
if ($request->has('id')) {
$ids = explode(',', $request->input('id'));
$user->whereIn('id', $ids);
}
//Use pagination
$users = $user->paginate(25);
/**
* Continue with the rest of response formatting below here
*/
}
Вы заметите, что я использовал функцию разбиения на страницы, чтобы ограничить результаты. При создании конечной точки API со списком ресурсов вы захотите поместить свои заголовки (мое предпочтение) или информацию тела ответа о том, как получить первую, предыдущую, следующую и последнюю страницу результатов. Функция разбивки на страницы в Laravel упрощает эту задачу, так как она может создавать большинство ссылок с использованием метода links()
.
К сожалению, вам нужно сообщить ему, какие параметры фильтра были переданы в запросе, чтобы он мог добавить их к генерируемым ссылкам. В противном случае вы получите ссылки без ваших фильтров, что не очень хорошо для клиента для пейджинга.
Итак, вот более полный пример записи параметров фильтра, чтобы их можно было добавить к ссылкам на страницы:
public function getIndex(Request $request)
{
//Create a User object to append WHERE clauses onto
$user = app('App\Models\User');
//List of filters we found to append to links later
$appends = [];
//Run through our simple text fields
foreach(['first_name', 'last_name', 'region', 'ip'] as $field) {
if ($request->has($field)) {
$appends[$field] = $request->input($field);
$user->where($field, $request->input($field));
}
}
//This field uses a LIKE match, handle it separately
if ($request->has('email')) {
$appends['email'] = $request->input('email');
$user->where('email', LIKE, '%' . $request->input('email') . '%');
}
//This field is a list of IDs
if ($request->has('id')) {
$appends['id'] = $request->input('id');
$ids = explode(',', $request->input('id'));
$user->whereIn('id', $ids);
}
//Use pagination
$users = $user->paginate(25);
//Make sure we append our filter parameters onto the pagination object
$users->appends($appends);
//Now calling $users->links() will return the correct links with the right filter info
/**
* Continue with the rest of response formatting below here
*/
}
Документацию по разбивке на страницы можно найти здесь: https://laravel.com/docs/5.2/pagination.
В качестве примера того, как можно замечательно сделать ссылки на страницы, ознакомьтесь с документацией API Github: https://developer.github.com/v3/#pagination
В конце концов, это не слишком далеко от того, что вы делали, концептуально. Преимущество здесь в том, что вы перемещаете код в метод, который в нем нуждается, вместо того, чтобы запускать его в своем конструкторе каждый раз при инициализации контроллера, даже если будет вызываться другой метод.
Надеюсь, это поможет!
person
stratedge
schedule
23.03.2016