динамический запрос, красноречивый с whereHas

Я хочу создавать динамические фильтры.
например я хочу создать этот код

$Contact = Contact::whereHas('User', function ($query) use ($searchString) {
$query->where('name', 'like', '%Jhone%')->orwhere('family', '<>' . 'Doe');
})->whereHas('Account', function ($query) use ($searchString) {
$query->where('account_name', '=' , 'test_account' )->orwhere('account_city', 'like', '%test_city%');
})->get();

и все параметры являются переменными
name,like,%Jhone%,family,<>,Doe, …..
и я хочу передать переменные в функцию и функцию создать запрос выше.

0

Решение

Я предполагаю, что отношения функционируют внутри вашего Contact, User а также Account модели написаны в camelCase и не PascalCase как показывает ваш пример.

public function getContacts(Request $request)
{
return Contact::when($request->get('username'), function ($query, $val) use ($request) {
$query->whereHas('user', function ($q) use ($val, $request) {
$q->where('name', 'like', '%'.$val.'%');
if ($request->has('familyname')) {
$q->orWhere('family', '<>', $request->get('familyname'));
}
});
})
->when($request->get('accountname'), function ($query, $val) use ($request) {
$query->whereHas('account', function ($q) use ($val, $request) {
$q->where('account_name', $val);
if ($request->has('city')) {
$q->orWhere('account_city', 'like', '%'.$request->get('city').'%');
}
});
})
->get();
}

Эта функция вернет все контакты, когда нет GET Параметры указаны по запросу. Если параметр для username присутствует, он будет возвращать только те контакты, для которых существует пользователь с указанным именем. Если к тому же familyname параметр присутствует, он даст контакты с пользователем, у которого совпадает имя пользователя или фамилия, отличная от указанной. То же самое относится к аккаунту, имени аккаунта и городу.

В частности, в этом примере есть две интересные вещи:

  • when($value, $callback) Функция может быть использована для создания очень динамических запросов, которые выполняют только $callback когда $value правда. Если вы используете $request->get('something') а также something не доступен в качестве параметра, функция вернет null и обратный вызов не выполняется. Сам обратный вызов имеет форму function ($query, $value) { ... }, где $value переменная, которую вы передали when() в качестве первого параметра.
  • С помощью $request->has('something') внутри функций построителя запросов для динамического построения ограничений на запрос является альтернативой when(), Я добавил его только для демонстрации — в общем, я бы рекомендовал придерживаться одного стиля.

Если бы вы расширили пример, вы могли бы также создавать высокодинамичные запросы, где не только переменное содержимое, например Doe для фамилии дается в качестве параметров, но и компаратор, как =, <> или же like, Но дальнейшее развитие этой темы — слишком много для этого ответа, и в любом случае уже есть учебники по этой теме.


Изменить: вот пример для динамического запроса с более подробным вводом

Ожидаемый ввод (немного отличается от вашего запроса, потому что ваш не может работать):

$filters = [
'user' => [
['name','like','%Jhone%'],
['family','<>','Doe'],
],
'account' => [
['account_name','=','test_account'],
['account_city','like','%test_city%'],
]
];

И функция:

public function getContacts(Request $request, array $filters)
{
$query = Contact::query();

foreach ($filters as $key => $constraints) {
$query->whereHas($key, function ($q) use ($constraints) {
if (count($constraints) > 0) {
$q->where($constraints[0][0], $constraints[0][1], $constraints[0][2]);
}
for ($i = 1; $i < count($constraints); $i++) {
$q->orWhere($constraints[$i][0], $constraints[$i][1], $constraints[$i][2]);
}
});
}

return $query->get();
}

Это всегда будет использовать OR для нескольких ограничений, а не AND, С помощью AND а также OR Смешанный потребует гораздо более сложной системы.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]