Почему поисковый запрос laravel не работает?

#php #mysql #laravel #eloquent

Вопрос:

У меня есть users таблица с отделом и ролью. Это отношения «многие ко многим». Итак, ниже приведены таблицы,

  • Пользователи
  • отделы
  • роли
  • users_departments
  • users_roles

Со следующими моделями,

  1. Пользователь
  2. Роль
  3. Отдел

В пользовательской модели у меня есть следующее

 class User extends Authenticatable
{
    public function scopeSearch($query, $searchValues)
    {
        return $query->where('first_name','like', '%'.$searchValues.'%')
        ->orWhere('last_name','like', '%'.$searchValues.'%')
        ->orWhere('email','like', '%'.$searchValues.'%');
    }
    
    public function departments()
    {
        return $this->belongsToMany(Department::class, 'users_departments', 'user_id', 'department_id');
    }

    public function roles()
    {
       return $this->belongsToMany(Role::class, 'users_roles', 'user_id', 'role_id');
    }
}
 

У меня есть необработанный запрос, который работает для меня, вы можете увидеть его ниже

 SELECT users.id as id, users.first_name as first_name, users.last_name as last_name, users.email as email, roles.title as `role`, departments.title as department 
FROM users INNER JOIN users_departments ON users_departments.user_id = users.id 
INNER JOIN departments ON departments.id = users_departments.department_id 
INNER JOIN users_roles ON users_roles.user_id = users.id 
INNER JOIN roles ON roles.id = users_roles.role_id 
WHERE `departments`.`title` LIKE '%".$search."%' 
OR `roles`.`title` LIKE '%".$search."%' 
OR `first_name` LIKE '%".$search."%' 
OR `last_name` LIKE '%".$search."%' 
OR `email` LIKE '%".$search."%' 
GROUP BY users.id 
ORDER BY " . $orderColumnName. " " . $order
 

Что я пробовал?

Я пытаюсь выполнить следующий запрос, который ничего не возвращает,

 $query = User::with([
    'roles' => function($query) use($searchValues) {
        return $query->where('title', 'LIKE','%'.$searchValues.'%');
    }, 
    'departments' => function($query) use($searchValues) {
        return $query->where('title', 'LIKE','%'.$searchValues.'%');

    }
])
->search($searchValues)
->orderBy($orderColumnName,$order)
->limit($request->length)
->get();
 

может кто-нибудь любезно подсказать мне, в чем проблема, чтобы я мог ее исправить? Я признателен, если кто-нибудь поможет мне это исправить.

Спасибо

Комментарии:

1. Что такое search метод в вашем запросе? Это область видимости?

2. @MichalOravec да, верно, я упомянул в вопросе. Вы можете видеть в пользовательской модели

3. При работе со сложными запросами я сначала правильно выполняю запрос, как вы это сделали, а затем выгружаю созданный sql, чтобы вы могли сравнить его. Затем просто продолжайте уточнять, пока не получите то же самое.

4. Просто чтобы добавить к этому, я думаю, вы обнаружите, что ->with() не даст желаемого результата. Вам нужно внутреннее соединение, поэтому я бы попробовал -> join() .

Ответ №1:

Всегда будьте осторожны с orWhere .

https://laravel.com/docs/8.x/queries#logical-grouping

Вы всегда должны группировать вызовы orWhere, чтобы избежать неожиданного поведения при применении глобальных областей.

Но в вашем случае это желаемое поведение.

Вам не хватает фильтрации ваших отношений, вы можете сделать это с orWhereHas помощью .

https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence

 $users = User::with(['roles' => $closure = function ($query) use ($searchValues) {
            return $query->where('title', 'LIKE', "%{$searchValues}");
        }, 'departments' => $closure
    ])->orWhereHas('roles', $closure)
    ->orWhereHas('departments', $closure)
    ->search($searchValues)
    ->orderBy($orderColumnName, $order)
    ->limit($request->length)
    ->get();
 

Я сохранил закрытие переменной, потому что оно повторяется в запросе.

Комментарии:

1. Спасибо за ваш ответ, я попробовал. К сожалению, он не работает

2. «Это не работает» не очень полезно.