Laravel. Работа с БД. Часть вторая — конструктор запроса

21.11.2020

Теги: LaravelMySQLPHPWeb-разработкаБазаДанныхКлассТаблицаТеорияФреймворк

Конструктор запроса (Query Builder)

Конструктор запроса предоставляет удобный интерфейс для создания и выполнения запросов к базе данных. И может использоваться для выполнения большинства типов операций. Конструктор использует привязку параметров к запросам средствами PDO для защиты от SQL-инъекций. Нет необходимости экранировать строки перед их передачей в запрос.

8. Слияние запросов (UNION)

Можно создать начальный запрос и с помощью метода union() слить его со вторым запросом:

$first = DB::table('users')
    ->whereNull('first_name');

$users = DB::table('users')
    ->whereNull('last_name')
    ->union($first)
    ->get();

9. Условие выборки (WHERE)

Для добавления в запрос условий WHERE используйте метод where на экземпляре конструктора запросов. Самый простой вызов where() требует три аргумента: имя столбца, оператор и значение для сравнения со столбцом.

$users = DB::table('users')->select('name', 'email')->where('name', '=', 'Сергей Иванов')->get();
$users = DB::table('users')->select('name', 'email')->where('name', 'Сергей Иванов')->get();
SELECT `name`, `email` FROM `users` WHERE `name` = 'Сергей Иванов'

В метод where() также можно передать массив условий:

$users = DB::table('users')
    ->select('name', 'email')
    ->where([
        ['admin', '=', false],
        ['name', 'like', '%Иванов%'],
    ])->get();
SELECT `name`, `email` FROM `users` WHERE (`admin` = 0 AND `name` LIKE '%Иванов%')

Если where() вызывается несколько раз — это означает использование AND:

$users = DB::table('users')
    ->select('name', 'email')
    ->where('admin', '=', false)
    ->where('name', 'like', '%Иванов%')
    ->get();
SELECT `name`, `email` FROM `users` WHERE `admin` = 0 AND `name` LIKE '%Иванов%'

Метод orWhere() позволяет использовать OR в условии WHERE:

$users = DB::table('users')
    ->select('name', 'email')
    ->where('email', 'like', '%ivanov%')
    ->orWhere('name', 'like', '%Иванов%')
    ->get();
SELECT `name`, `email` FROM `users` WHERE `email` LIKE '%ivanov%' OR `name` LIKE '%Иванов%'

Метод whereBetween() проверяет, что значение столбца находится в указанном интервале:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereBetween('role', [1,3])
    ->get();
SELECT `name`, `email` FROM `users` WHERE `role` BETWEEN 1 AND 3

Метод whereNotBetween() проверяет, что значение столбца находится вне указанного интервала:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereNotBetween('role', [1,3])
    ->get();
SELECT `name`, `email` FROM `users` WHERE `role` NOT BETWEEN 1 AND 3

Метод whereIn() проверяет, что значение столбца содержится в указанном массиве:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereIn('id', [1,2,3])
    ->get();
SELECT `name`, `email` FROM `users` WHERE `id` IN (1, 2, 3)

Метод whereNotIn() проверяет, что значение столбца содержится в указанном массиве:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereNotIn('id', [1,2,3])
    ->get();
SELECT `name`, `email` FROM `users` WHERE `id` NOT IN (1, 2, 3)

Метод whereNull() проверяет, что значение столбца равно NULL:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereNull('deleted_at')
    ->get();
SELECT `name`, `email` FROM `users` WHERE `deleted_at` IS NULL

Метод whereNotNull() проверяет, что значение столбца не равно NULL:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereNotNull('deleted_at')
    ->get();
SELECT `name`, `email` FROM `users` WHERE `deleted_at` IS NOT NULL

10. Условие выборки по дате

Метод whereDate() служит для сравнения значения столбца с указанной датой:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereDate('created_at', '2020-10-09')
    ->get();
SELECT `name`, `email` FROM `users` WHERE DATE(`created_at`) = '2020-10-09'

Метод whereMonth() служит для сравнения значения столбца с месяцем в году:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereMonth('created_at', '10')
    ->get();
SELECT `name`, `email` FROM `users` WHERE MONTH(`created_at`) = '10'

Метод whereDay() служит для сравнения значения столбца с днём месяца:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereDay('created_at', '09')
    ->get();
SELECT `name`, `email` FROM `users` WHERE DAY(`created_at`) = '09'

Метод whereYear() служит для сравнения значения столбца с указанным годом:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereYear('created_at', '2020')
    ->get();
SELECT `name`, `email` FROM `users` WHERE YEAR(`created_at`) = '2020'

11. Сравнение двух колонок

Для проверки на совпадение двух столбцов можно использовать метод whereColumn():

$users = DB::table('users')
    ->select('first_name', 'last_name')
    ->whereColumn('first_name', 'last_name')
    ->get();
SELECT `first_name`, `last_name` FROM `users` WHERE `first_name` = `last_name`

В метод также можно передать оператор сравнения:

$users = DB::table('users')
    ->select('name', 'email')
    ->whereColumn('updated_at', '>', 'created_at')
    ->get();
SELECT `name`, `email` FROM `users` WHERE `updated_at` > `created_at`

Также можно передать массив с несколькими условиями — они будут объединены оператором AND:

$users = DB::table('users')
    ->select('first_name', 'last_name')
    ->whereColumn([
        ['first_name', '=', 'last_name'],
        ['updated_at', '>', 'created_at']
    ])
    ->get();
SELECT `first_name`, `last_name` FROM `users` WHERE (`first_name` = `last_name` AND `updated_at` > `created_at`)

12. Группировка условий WHERE

Иногда нужно сделать выборку по более сложной группировкой условий, например (условие OR условие) AND (условие OR условие):

$users = DB::table('users')
    ->select('name', 'email')
    ->where(function ($query) {
        $query->where('admin', '=', false)
            ->orWhere('role', '<>', 'admin');
    })
    ->where(function ($query) {
        $query->where('votes', '>', 100)
            ->orWhereColumn('updated_at', '>', 'created_at');
    })
    ->get();
SELECT
    `name`, `email`
FROM
    `users`
WHERE
    (`admin` = 0 OR `role` <> 'admin') AND (`votes` > 100 OR `updated_at` > `created_at`)

Метод whereExists() позволяет написать SQL-условие WHERE EXISTS:

DB::table('users')
    ->whereExists(function ($query) {
        $query->select(DB::raw(1))
            ->from('orders')
            ->where('orders.user_id', '=', 'users.id');
    })
    ->get();
SELECT
    *
FROM
    `users`
WHERE
    EXISTS (SELECT 1 FROM `orders` WHERE `orders`.`user_id` = `users`.`id`)

Этим запросом мы выбираем из таблицы users только тех пользователей, которые сделали хотя бы один заказ в интернет-магазине.

13. Сортировка и группировка

Метод orderBy() позволяет отсортировать результат запроса по заданному столбцу. Первый аргумент метода — столбец для сортировки, а второй — задаёт направление сортировки и может быть либо asc, либо desc.

$users = DB::table('users')
    ->select('name', 'email')
    ->orderBy('name', 'desc')
    ->get();

Методы latest() и oldest() позволяют отсортировать результаты по дате. По умолчанию выполняется сортировка по столбцу created_at, но можно передать имя столбца для сортировки.

$users = DB::table('users')
    ->select('name', 'email')
    ->latest()
    ->first();

Для сортировки результатов запроса в случайном порядке можно использовать метод inRandomOrder():

// получить случайного пользователя
$users = DB::table('users')
    ->select('name', 'email')
    ->inRandomOrder()
    ->first();

Методы groupBy() и having() используются для группировки результатов запроса. Тут трудно привести какой-то пример использования, потому что HAVING подразумевает фильтрацию по значениям агрегатных функций.

Метод havingRaw() используется для передачи сырой строки в условие HAVING:

buyers = DB::table('orders')
    ->select('name', 'email', DB::raw('SUM(amount) as total'))
    ->groupBy('name', 'email')
    ->havingRaw('SUM(amount) > 10000')
    ->get();
SELECT
    `name`, `email`, SUM(`amount`) AS `total`
FROM
    `orders`
GROUP BY
    `name`, `email`
HAVING
    SUM(`amount`) > 10000
Illuminate\Support\Collection Object
(
    [items:protected] => Array
        (
            [0] => stdClass Object
                (
                    [name] => Дмитрий Николаев
                    [email] => nikolaev.d@mail.ru
                    [total] => 15349.00
                )
            [1] => stdClass Object
                (
                    [name] => Сергей Иванов
                    [email] => ivanov.s@mail.ru
                    [total] => 19824.00
                )
        )
)

Мы в этом запросе отбираем покупателей интернет-магазина, общая сумма покупок которых больше 10000 рублей.

Для ограничения числа возвращаемых результатов из запроса или для пропуска заданного числа результатов в запросе используются методы skip() и take().

$users = DB::table('users')->skip(10)->take(5)->get();

Или можно использовать методы limit() и offset():

$users = DB::table('users')->offset(10)->limit(5)->get();

14. Условные выражения

Иногда необходимо применять условие к запросу, только если выполняется какое-то другое условие. Например, выполнять where(), только если нужное значение есть во входящем http-запросе.

$role_id = request()->input('role_id');
$users = DB::table('users')
    ->select('name', 'email')
    ->when($role_id, function ($query) use ($role_id) {
        return $query->where('role_id', $role_id);
    })
    ->get();
SELECT `name`, `email` FROM `users` WHERE `role_id` = 2

Метод when() выполняет данное замыкание, только когда первый параметр равен true. Если первый параметр равен false, то замыкание не будет выполнено.

Можно передать ещё одно замыкание третьим параметром метода when(). Это замыкание будет выполнено, если первый параметр будет иметь значение false.

$sortBy = null;

$users = DB::table('users')
    ->select('name', 'email')
    ->when($sortBy, function ($query) use ($sortBy) {
        return $query->orderBy($sortBy);
    }, function ($query) {
        return $query->orderBy('name');
    })
    ->get();

Поиск: Laravel • MySQL • PHP • Web-разработка • База данных • Класс • Таблица • Фреймворк • Query Builder

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.