Laravel использует великолепный механизм работы с базами данных под названием Eloquent, плюс имеет мощный Конструктор Запросов (Query Builder), но иногда необходимо написать просто «сырой» запрос (Raw Queries). В этой статье я покажу вам несколько способов, как это сделать.
1. Самый типичный: selectRaw() с вычислениями Avg/Sum/Count
Если вам нужно выполнить groupBy()
, а затем использовать какую-либо агрегирующую функцию MySQL, например AVG()
или COUNT()
, то будет полезным выполнение «сырого» запроса для конкретной секции.
Пример из документации Laravel:
$users = DB::table('users') ->selectRaw('count(*) as user_count, status') ->where('status', '<>', 1) ->groupBy('status') ->get();
Другой пример:
$products = DB::table('products') ->leftjoin('category','category.product_id','=','products.id') ->selectRaw('COUNT(*) as nbr', 'products.*') ->groupBy('products.id') ->get();
Еще один пример — мы даже можем выполнить одновременно и avg()
, и count()
.
$salaries = DB::table('salaries') ->selectRaw('companies.name as company_name, avg(salary) as avg_salary, count(*) as people_count') ->join('companies', 'salaries.company_id', '=', 'companies.id') ->groupBy('companies.id') ->orderByDesc('avg_salary') ->get();
2. Фильтруем Год: groupByRaw, orderByRaw и havingRaw
А если вам нужно добавить какие-либо SQL-вычисления в group by
или order by
? Для этого у нас есть такие методы, как groupByRaw()
и orderByRaw()
. Кроме того, мы можем использовать дополнительный where
после группировки, используя оператор havingRaw()
.
Например, как сгруппировать по ГОДУ определенные поля форматов дата/время?
$results = User::selectRaw('YEAR(birth_date) as year, COUNT(id) as amount') ->groupByRaw('YEAR(birth_date)') ->havingRaw('YEAR(birth_date) > 2000') ->orderByRaw('YEAR(birth_date)') ->get();
3. Вычисление поля с помощью подзапроса: selectRaw()
Если вам нужно получить конкретный результат путем расчета данных в имеющихся полях и вы хотите, чтобы это происходило в SQL-запросе, то вот как это можно сделать:
$products = Product::select('id', 'name') ->selectRaw('price - discount_price AS discount') ->get();
Другой пример — оператор CASE
:
$users = DB::table('users') ->select('name', 'surname') ->selectRaw("(CASE WHEN (gender = 1) THEN 'M' ELSE 'F' END) as gender_text") ->get();
4. Старый добрый SQL-запрос? Просто используйте DB::select()
Довольно типичный пример: у вас есть SQL-выражение из старого проекта, и вам нужно использовать его в Laravel. Тут поможет DB::select()
.
$results = DB::select('select * from users where id = ?', [1]);
5. DB::Statement() — обычно для миграций
Если вам нужно выполнить какой-либо SQL-запрос без обработки результата, например, INSERT
или UPDATE
без параметров, то вы можете использовать DB::Statement()
.
По моему опыту, это часто используется в миграциях для базы данных, когда структуры некоторых таблиц поменялись и необходимо привести старые данные к новой структуре.
DB::statement('UPDATE users SET role_id = 1 WHERE role_id IS NULL AND YEAR(created_at) > 2020');
Кроме того, DB::Statement()
может выполнить любой SQL-запрос для управления таблицами и базами данных.
DB::statement('DROP TABLE users'); DB::statement('ALTER TABLE projects AUTO_INCREMENT=123');
Предупреждение: будьте осторожны, всегда проверяйте параметры
Самая большая опасность сырых запросов заключается в том, что они не защищаются автоматически, поэтому, если вы передаете в запрос какие-либо параметры, пожалуйста, трижды их проверьте! Убедитесь в валидности их значений (например, что это число, а не строка) и формата.
Автор: Povilas Korop
Перевод: Алексей Широков
Наш Телеграм-канал — следите за новостями о Laravel.