Все разработчики, рано или поздно, начинают понимать что стандартными средствами ORM библиотеки невозможно реализовать сложные и удобные запросы.
То тут, мы не знаем как написать простейших запрос для подсчёта суммы, без вынимания всех значений, то там, мы не можем составить нетривиальное условие.
В большинстве случаев, кроме удобного доступа к данным, ORM библиотеки доставляют нам головную боль с составлением сложных запросов и огромное количество избыточных выборок.
Сегодня я хочу рассказать, как мы можем обойти часть сложностей и упростить себе работу и, возможно, снизить нагрузку на сервер, используя ORM Jelly.
Выбираем только нужные нам поля
Для указания какие поля нам нужно возратить в кортеже, можно использовать функцию select()
Например:
// Простая выборка только нужных полей
Jelly::select('user')
->select('id','name')
-execute();
// Выбираем все поля
Jelly::select('user')
->select('*')
-execute();
// Суммируем значения по колонке
Jelly::select('transactions')
->select('title', DB::expr("SUM('money') AS money"))
-execute();
// Выбираем все колонки из одной таблицы, и избранные из другой
Jelly::select('user')
->select(DB::expr('`users`.*'), DB::expr("`providers`.`id` AS provider_id"))
-execute();
Тут важно помнить, что если какие-то из полей в кортеже у нас не были описаны в модели, то и доступ к ним мы получить привычным способом не сможем.
Для этого нам нужно использовать функцию get('field')
Как-то так:
// Суммируем значения по колонке
$transactions = Jelly::select('transactions')
->select('title', DB::expr("SUM('money') AS money"))
->execute();
// Выводим сумму
foreach ($transactions as $transaction) {
echo $transaction->title . " " . $transactions->get('money');
}
То что нужно знать
Конечно же, вы должны уже знать как можно группировать условия логически и умеете пользоваться операторами JOIN и WITH (про них описано в официальной справке, если что).
Например вот этот поток сознания вам поможет сориентироваться в обстановке
$builder = Jelly::select('users')
->join('provider', 'left')
->on('provider.user_id', '=', 'user.id')
->on('provider.name', 'LIKE', 'NBN%')
->where('date_reg', '>', '2010-01-01')
->and_where('active', '=', 1)
->or_where_open()
->where('admin', '=', 1)
->or_where_close()
->execute();
До того как вы вызовете execute()
или load()
вы всегда можете посмотреть что у нас получается в билдере запросов. Для этого его можно просто вывести на печать.
$builder = Jelly::select('users')
->where('date_reg', '>', '2010-01-01');
// Выводим получившийся запрос
print $builder;
$users = $builder->execute();
Так же, важно знать что код обёрнутый DB::expr('code')
не обрабатывается билдером. Что позволяет нам транслировать в него прямые куски SQL кода.
Подзапросы
Теперь можно попробовать составить что-то необычное, например подзапросы. Внимание, лучше сесть :)
$subquery = Jelly::select('price')
->select(DB::expr('SUM(price.spec) AS `spec`'))
->where('providers.id', '=', DB::expr('`price`.`provider_id`'))
->and_where('price.group_id', '=', DB::expr('`groups`.`group_id`'));
$builder = Jelly::select('user')
->select('`provider`.*', DB::expr('('.$subquery . ') AS `spec`'))
->distinct(TRUE)
->order_by('spec', 'DESC')
->execute();
Этот код не обладает красотой и теми плюшечками ORM которые нам предоставлены из коробки, но именно этот код позволяет писать гибкие запросы.