Документация Laravel 10.x
Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.
Конструктор запросов к базе данных Laravel предоставляет удобный, плавный интерфейс для создания и выполнения запросов к базе данных. Его можно использовать для выполнения большинства операций с базой данных в вашем приложении и отлично работает с всеми поддерживаемыми системами управления базами данных Laravel.
Конструктор запросов Laravel использует привязку параметров PDO для защиты вашего приложения от атак SQL-инъекций. Нет необходимости очищать или санитаризировать строки, передаваемые построителю запросов, как привязки запросов.
Внимание PDO не поддерживает привязку имен столбцов. Поэтому никогда не допускайте ввод пользовательских данных для определения имен столбцов, на которые ссылаются ваши запросы, включая столбцы "order by".
Вы можете использовать метод table
предоставленный фасадом DB
для начала запроса. Метод table
возвращает экземпляр построителя запросов для данной таблицы, позволяя вам добавлять более многочисленные ограничения к запросу, а затем, наконец, извлекать результаты запроса, используя метод get
:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use Illuminate\Support\Facades\DB;use Illuminate\View\View; class UserController extends Controller{ /** * Показать список всех пользователей приложения. */ public function index(): View { $users = DB::table('users')->get(); return view('user.index', ['users' => $users]); }}
Метод get
возвращает экземпляр Illuminate\Support\Collection
, содержащий результаты запроса, где каждый результат представляет собой экземпляр объекта PHP stdClass
. Вы можете получить доступ к значению каждого столбца, обращаясь к столбцу как к свойству объекта:
use Illuminate\Support\Facades\DB; $users = DB::table('users')->get(); foreach ($users as $user) { echo $user->name;}
Примечание Коллекции Laravel предоставляют разнообразные мощные методы для отображения и сокращения данных. Дополнительную информацию о коллекциях Laravel можно найти в документации по коллекциям.
Если вам просто нужно извлечь одну строку из таблицы базы данных, вы можете использовать метод first
фасада DB
. Этот метод вернет один объект stdClass
:
$user = DB::table('users')->where('name', 'John')->first(); return $user->email;
Если вам не нужна вся строка, вы можете извлечь единственное значение из записи с использованием метода value
. Этот метод вернет значение столбца напрямую:
$email = DB::table('users')->where('name', 'John')->value('email');
Для получения одной строки по значению столбца id
используйте метод find
:
$user = DB::table('users')->find(3);
Если вы хотите получить экземпляр Illuminate\Support\Collection
, содержащий значения одного столбца, вы можете использовать метод pluck
. В этом примере мы получим коллекцию заголовков пользователей:
use Illuminate\Support\Facades\DB; $titles = DB::table('users')->pluck('title'); foreach ($titles as $title) { echo $title;}
Вы можете указать столбец, который должен использоваться в качестве ключей результирующей коллекции, предоставив второй аргумент методу pluck
:
$titles = DB::table('users')->pluck('title', 'name'); foreach ($titles as $name => $title) { echo $title;}
Если вам нужно работать с тысячами записей в базе данных, рассмотрите использование метода chunk
, предоставляемого фасадом DB
. Этот метод извлекает небольшой кусок результатов за раз и передает каждый кусок в замыкание для обработки. Например, давайте извлечем все записи из таблицы users
порциями по 100 записей за раз:
use Illuminate\Support\Collection;use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) { foreach ($users as $user) { // ... }});
Вы можете предотвратить обработку дополнительных порций, вернув false
из замыкания:
DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) { // Обработка записей... return false;});
Если вы обновляете записи в базе данных во время обработки результатов по порциям, ваши результаты могут измениться неожиданным образом. Если вы планируете обновлять полученные записи во время обработки по порциям, лучше всего использовать метод chunkById
. Этот метод автоматически разбивает результаты на страницы на основе первичного ключа записи:
DB::table('users')->where('active', false) ->chunkById(100, function (Collection $users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } });
Внимание При обновлении или удалении записей внутри обратного вызова чанка любые изменения первичного ключа или внешних ключей могут повлиять на запрос чанка. Это может потенциально привести к тому, что записи не будут включены в результаты чанка.
Метод lazy
работает аналогично методу chunk
в том смысле, что выполняет запрос порциями. Однако вместо передачи каждой порции в обратный вызов, метод lazy()
возвращает LazyCollection
, который позволяет вам взаимодействовать с результатами как с одним потоком:
use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->lazy()->each(function (object $user) { // ...});
Еще раз, если вы планируете обновлять полученные записи во время их итерации, лучше всего использовать методы lazyById
или lazyByIdDesc
. Эти методы автоматически разбивают результаты на страницы на основе первичного ключа записи:
DB::table('users')->where('active', false) ->lazyById()->each(function (object $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); });
Внимание При обновлении или удалении записей во время их итерации любые изменения первичного ключа или внешних ключей могут повлиять на запрос чанка. Это может потенциально привести к тому, что записи не будут включены в результаты.
Конструктор запросов также предоставляет разнообразные методы для извлечения агрегированных значений, таких как count
, max
, min
, avg
и sum
. Вы можете вызвать любой из этих методов после построения вашего запроса:
use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); $price = DB::table('orders')->max('price');
Конечно же, вы можете комбинировать эти методы с другими условиями для тонкой настройки того, как рассчитывается ваше агрегированное значение:
$price = DB::table('orders') ->where('finalized', 1) ->avg('price');
Вместо использования метода count
для определения того, существуют ли записи, соответствующие вашим условиям запроса, вы можете использовать методы exists
и doesntExist
:
if (DB::table('orders')->where('finalized', 1)->exists()) { // ...} if (DB::table('orders')->where('finalized', 1)->doesntExist()) { // ...}
Возможно, вам не всегда нужно выбирать все столбцы из таблицы базы данных. Используя метод select
, вы можете указать пользовательский "select" клоз для запроса:
use Illuminate\Support\Facades\DB; $users = DB::table('users') ->select('name', 'email as user_email') ->get();
Метод distinct
позволяет принудительно вернуть уникальные результаты запроса:
$users = DB::table('users')->distinct()->get();
Если у вас уже есть экземпляр построителя запросов и вы хотите добавить столбец к его существующему "select" клозу, вы можете использовать метод addSelect
:
$query = DB::table('users')->select('name'); $users = $query->addSelect('age')->get();
Иногда вам может потребоваться вставить произвольную строку в запрос. Для создания сырого строкового выражения вы можете использовать метод raw
, предоставленный фасадом DB
:
$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();
Внимание Сырые операторы будут внедрены в запрос в виде строк, поэтому вы должны быть чрезвычайно осторожны, чтобы избежать создания уязвимостей для SQL-инъекций.
Вместо использования метода DB::raw
, вы также можете использовать следующие методы для вставки сырого выражения в различные части вашего запроса. Помните, что Laravel не может гарантировать, что любой запрос с использованием сырых выражений защищен от уязвимостей SQL-инъекций.
selectRaw
Метод selectRaw
можно использовать вместо addSelect(DB::raw(/* ... */))
. Этот метод принимает необязательный массив привязок в качестве второго аргумента:
$orders = DB::table('orders') ->selectRaw('price * ? as price_with_tax', [1.0825]) ->get();
whereRaw / orWhereRaw
Методы whereRaw
и orWhereRaw
могут быть использованы для вставки сырого "where" выражения в ваш запрос. Эти методы принимают необязательный массив привязок в качестве своего второго аргумента:
$orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get();
havingRaw / orHavingRaw
Методы havingRaw
и orHavingRaw
могут быть использованы для предоставления сырой строки в качестве значения выражения "having". Эти методы также принимают необязательный массив привязок в качестве второго аргумента:
$orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get();
orderByRaw
Метод orderByRaw
может быть использован для предоставления сырой строки в качестве значения выражения "order by":
$orders = DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get();
groupByRaw
Метод groupByRaw
может быть использован для предоставления сырой строки в качестве значения выражения group by
:
$orders = DB::table('orders') ->select('city', 'state') ->groupByRaw('city, state') ->get();
Конструктор запросов также может использоваться для добавления операторов соединения к вашим запросам. Для выполнения базового "inner join" вы можете использовать метод join
на экземпляре построителя запросов. Первый аргумент, переданный методу join
, - это имя таблицы, к которой вы хотите присоединиться, а оставшиеся аргументы указывают ограничения столбцов для соединения. Вы можете даже присоединить несколько таблиц в одном запросе:
use Illuminate\Support\Facades\DB; $users = DB::table('users') ->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get();
Если вы хотите выполнить "left join" или "right join" вместо "inner join", используйте методы leftJoin
или rightJoin
. Эти методы имеют тот же формат, что и метод join
:
$users = DB::table('users') ->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); $users = DB::table('users') ->rightJoin('posts', 'users.id', '=', 'posts.user_id') ->get();
Метод crossJoin
может быть использован для выполнения "cross join". Cross join создает декартово произведение между первой таблицей и присоединенной таблицей:
$sizes = DB::table('sizes') ->crossJoin('colors') ->get();
Вы также можете указать более сложные условия соединения. Для начала передайте замыкание в качестве второго аргумента методу join
. Замыкание получит экземпляр Illuminate\Database\Query\JoinClause
, который позволяет указать ограничения в выражении "join":
DB::table('users') ->join('contacts', function (JoinClause $join) { $join->on('users.id', '=', 'contacts.user_id')->orOn(/* ... */); }) ->get();
Если вы хотите использовать условие "where" для ваших соединений, вы можете использовать методы where
и orWhere
, предоставленные экземпляром JoinClause
. Вместо сравнения двух столбцов эти методы сравнивают столбец с значением:
DB::table('users') ->join('contacts', function (JoinClause $join) { $join->on('users.id', '=', 'contacts.user_id') ->where('contacts.user_id', '>', 5); }) ->get();
Методы joinSub
, leftJoinSub
и rightJoinSub
могут быть использованы для присоединения запроса к подзапросу. Каждый из этих методов принимает три аргумента: подзапрос, его псевдоним таблицы и замыкание, которое определяет связанные столбцы. В этом примере мы получим коллекцию пользователей, где каждая запись пользователя также содержит метку времени created_at
последней опубликованной статьи блога пользователя:
$latestPosts = DB::table('posts') ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at')) ->where('is_published', true) ->groupBy('user_id'); $users = DB::table('users') ->joinSub($latestPosts, 'latest_posts', function (JoinClause $join) { $join->on('users.id', '=', 'latest_posts.user_id'); })->get();
Конструктор запросов также предоставляет удобный метод для "объединения" двух или более запросов. Например, вы можете создать первоначальный запрос и использовать метод union
, чтобы объединить его с дополнительными запросами:
use Illuminate\Support\Facades\DB; $first = DB::table('users') ->whereNull('first_name'); $users = DB::table('users') ->whereNull('last_name') ->union($first) ->get();
В дополнение к методу union
Конструктор запросов предоставляет метод unionAll
. Запросы, объединенные с использованием метода unionAll
, не будут иметь удаленных повторяющихся результатов. Метод unionAll
имеет тот же формат, что и метод union
.
Вы можете использовать метод where
построителя запросов для добавления выражений "where" в запрос. Самый базовый вызов метода where
требует три аргумента. Первый аргумент - это имя столбца. Второй аргумент - оператор, который может быть любым из поддерживаемых базой данных операторов. Третий аргумент - это значение, с которым будет сравниваться значение столбца.
Например, следующий запрос извлекает пользователей, где значение столбца votes
равно 100
, а значение столбца age
больше 35
:
$users = DB::table('users') ->where('votes', '=', 100) ->where('age', '>', 35) ->get();
Для удобства, если вы хотите проверить, что столбец =
данному значению, вы можете передать значение вторым аргументом методу where
. Laravel предположит, что вы хотите использовать оператор =
:
$users = DB::table('users')->where('votes', 100)->get();
Как уже упоминалось, вы можете использовать любой оператор, поддерживаемый вашей системой управления базой данных:
$users = DB::table('users') ->where('votes', '>=', 100) ->get(); $users = DB::table('users') ->where('votes', '<>', 100) ->get(); $users = DB::table('users') ->where('name', 'like', 'T%') ->get();
Вы также можете передать массив условий функции where
. Каждый элемент массива должен быть массивом, содержащим три аргумента, как правило, передаваемых методу where
:
$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'],])->get();
Внимание PDO не поддерживает привязку имен столбцов. Поэтому никогда не допускайте ввод пользовательских данных для определения имен столбцов, на которые ссылаются ваши запросы, включая столбцы "order by".
При последовательном вызове метода where
построителя запросов выражения "where" будут объединяться с использованием оператора and
. Однако вы можете использовать метод orWhere
, чтобы объединить выражение с запросом, используя оператор or
. Метод orWhere
принимает те же аргументы, что и метод where
:
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere('name', 'John') ->get();
Если вам нужно сгруппировать условие "or" в скобки, вы можете передать замыкание в качестве первого аргумента методу orWhere
:
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere(function (Builder $query) { $query->where('name', 'Abigail') ->where('votes', '>', 50); }) ->get();
В приведенном выше примере будет создан следующий SQL-запрос:
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
Внимание Всегда группируйте вызовы
orWhere
, чтобы избежать неожиданного поведения при применении глобальных областей.
Методы whereNot
и orWhereNot
могут быть использованы для отрицания заданной группы ограничений запроса. Например, следующий запрос исключает продукты, которые находятся на распродаже или у которых цена меньше десяти:
$products = DB::table('products') ->whereNot(function (Builder $query) { $query->where('clearance', true) ->orWhere('price', '<', 10); }) ->get();
Laravel также поддерживает запросы к типам столбцов JSON в базах данных, которые предоставляют поддержку типов столбцов JSON. В настоящее время это включает MySQL 5.7+, PostgreSQL, SQL Server 2016 и SQLite 3.39.0 (с расширением JSON1). Для запроса к столбцу JSON используйте оператор ->
:
$users = DB::table('users') ->where('preferences->dining->meal', 'salad') ->get();
Вы можете использовать whereJsonContains
для запроса массивов JSON. Эта функция не поддерживается версиями базы данных SQLite менее 3.38.0:
$users = DB::table('users') ->whereJsonContains('options->languages', 'en') ->get();
Если ваше приложение использует базы данных MySQL или PostgreSQL, вы можете передать массив значений методу whereJsonContains
:
$users = DB::table('users') ->whereJsonContains('options->languages', ['en', 'de']) ->get();
Метод whereJsonLength
можно использовать для запроса массивов JSON по их длине:
$users = DB::table('users') ->whereJsonLength('options->languages', 0) ->get(); $users = DB::table('users') ->whereJsonLength('options->languages', '>', 1) ->get();
whereBetween / orWhereBetween
Метод whereBetween
проверяет, что значение столбца находится между двумя значениями:
$users = DB::table('users') ->whereBetween('votes', [1, 100]) ->get();
whereNotBetween / orWhereNotBetween
Метод whereNotBetween
проверяет, что значение столбца находится вне двух значений:
$users = DB::table('users') ->whereNotBetween('votes', [1, 100]) ->get();
whereBetweenColumns / whereNotBetweenColumns / orWhereBetweenColumns / orWhereNotBetweenColumns
Метод whereBetweenColumns
проверяет, что значение столбца находится между двумя значениями двух столбцов в одной строке таблицы:
$patients = DB::table('patients') ->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight']) ->get();
Метод whereNotBetweenColumns
проверяет, что значение столбца находится вне двух значений двух столбцов в одной строке таблицы:
$patients = DB::table('patients') ->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight']) ->get();
whereIn / whereNotIn / orWhereIn / orWhereNotIn
Метод whereIn
проверяет, что значение заданного столбца содержится в заданном массиве:
$users = DB::table('users') ->whereIn('id', [1, 2, 3]) ->get();
Метод whereNotIn
проверяет, что значение заданного столбца не содержится в заданном массиве:
$users = DB::table('users') ->whereNotIn('id', [1, 2, 3]) ->get();
Вы также можете предоставить объект запроса вторым аргументом метода whereIn
:
$activeUsers = DB::table('users')->select('id')->where('is_active', 1); $users = DB::table('comments') ->whereIn('user_id', $activeUsers) ->get();
Приведенный выше пример приведет к следующему SQL-запросу:
select * from comments where user_id in ( select id from users where is_active = 1)
Внимание Если вы добавляете большой массив целочисленных привязок к вашему запросу, вы можете использовать методы
whereIntegerInRaw
илиwhereIntegerNotInRaw
, чтобы значительно снизить использование памяти.
whereNull / whereNotNull / orWhereNull / orWhereNotNull
Метод whereNull
проверяет, что значение заданного столбца равно NULL
:
$users = DB::table('users') ->whereNull('updated_at') ->get();
Метод whereNotNull
проверяет, что значение столбца не равно NULL
:
$users = DB::table('users') ->whereNotNull('updated_at') ->get();
whereDate / whereMonth / whereDay / whereYear / whereTime
Метод whereDate
может быть использован для сравнения значения столбца с датой:
$users = DB::table('users') ->whereDate('created_at', '2016-12-31') ->get();
Метод whereMonth
может быть использован для сравнения значения столбца с определенным месяцем:
$users = DB::table('users') ->whereMonth('created_at', '12') ->get();
Метод whereDay
может быть использован для сравнения значения столбца с определенным днем месяца:
$users = DB::table('users') ->whereDay('created_at', '31') ->get();
Метод whereYear
может быть использован для сравнения значения столбца с определенным годом:
$users = DB::table('users') ->whereYear('created_at', '2016') ->get();
Метод whereTime
может быть использован для сравнения значения столбца с определенным временем:
$users = DB::table('users') ->whereTime('created_at', '=', '11:20:45') ->get();
whereColumn / orWhereColumn
Метод whereColumn
может быть использован для проверки равенства двух столбцов:
$users = DB::table('users') ->whereColumn('first_name', 'last_name') ->get();
Вы также можете передать оператор сравнения методу whereColumn
:
$users = DB::table('users') ->whereColumn('updated_at', '>', 'created_at') ->get();
Также вы можете передать массив сравнений столбцов методу whereColumn
. Эти условия будут объединены с использованием оператора and
:
$users = DB::table('users') ->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'], ])->get();
Иногда вам может потребоваться сгруппировать несколько условий "where" в скобках, чтобы добиться нужной логической группировки запроса. Фактически, вы должны обязательно группировать вызовы метода orWhere
в скобках, чтобы избежать непредвиденного поведения запроса. Для этого вы можете передать замыкание методу where
:
$users = DB::table('users') ->where('name', '=', 'John') ->where(function (Builder $query) { $query->where('votes', '>', 100) ->orWhere('title', '=', 'Admin'); }) ->get();
Как видно из примера выше, передача замыкания методу where
указывает построителю запросов начать группу ограничений. Замыкание получит экземпляр построителя запросов, который вы можете использовать для установки ограничений, которые должны находиться внутри группы скобок. Приведенный выше пример приведет к следующему SQL-запросу:
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
Внимание Всегда группируйте вызовы
orWhere
, чтобы избежать неожиданного поведения при применении глобальных областей.
Метод whereExists
позволяет вам создавать SQL-выражения "where exists". Метод whereExists
принимает замыкание, которое получит экземпляр построителя запросов, позволяя вам определить запрос, который должен находиться внутри выражения "exists":
$users = DB::table('users') ->whereExists(function (Builder $query) { $query->select(DB::raw(1)) ->from('orders') ->whereColumn('orders.user_id', 'users.id'); }) ->get();
В качестве альтернативы вы можете предоставить объект запроса методу whereExists
вместо замыкания:
$orders = DB::table('orders') ->select(DB::raw(1)) ->whereColumn('orders.user_id', 'users.id'); $users = DB::table('users') ->whereExists($orders) ->get();
Оба приведенных выше примера приведут к следующему SQL-запросу:
select * from userswhere exists ( select 1 from orders where orders.user_id = users.id)
Иногда вам может потребоваться построить условие "where", которое сравнивает результаты подзапроса с заданным значением. Вы можете сделать это, передав замыкание и значение методу where
. Например, следующий запрос извлечет всех пользователей с последней "membership" заданного типа:
use App\Models\User;use Illuminate\Database\Query\Builder; $users = User::where(function (Builder $query) { $query->select('type') ->from('membership') ->whereColumn('membership.user_id', 'users.id') ->orderByDesc('membership.start_date') ->limit(1);}, 'Pro')->get();
Или вам может потребоваться построить условие "where", которое сравнивает столбец с результатами подзапроса. Вы можете сделать это, передав столбец, оператор и замыкание методу where
. Например, следующий запрос извлечет все записи о доходах, где сумма меньше средней;
use App\Models\Income;use Illuminate\Database\Query\Builder; $incomes = Income::where('amount', '<', function (Builder $query) { $query->selectRaw('avg(i.amount)')->from('incomes as i');})->get();
Внимание Как на данный момент полные текстовые операторы where поддерживаются только MySQL и PostgreSQL.
Методы whereFullText
и orWhereFullText
могут быть использованы для добавления полнотекстовых условий "where" в запрос для столбцов, имеющих полнотекстовые индексы. Эти методы будут преобразованы в соответствующий SQL для используемой базы данных Laravel. Например, для приложений, использующих MySQL, будет сгенерировано условие MATCH AGAINST
:
$users = DB::table('users') ->whereFullText('bio', 'web developer') ->get();
orderBy
Метод orderBy
позволяет сортировать результаты запроса по заданному столбцу. Первый аргумент, принимаемый методом orderBy
, должен быть столбцом, по которому вы хотите сортировать, в то время как второй аргумент определяет направление сортировки и может быть либо asc
, либо desc
:
$users = DB::table('users') ->orderBy('name', 'desc') ->get();
Для сортировки по нескольким столбцам вы можете просто вызвать orderBy
столько раз, сколько необходимо:
$users = DB::table('users') ->orderBy('name', 'desc') ->orderBy('email', 'asc') ->get();
latest
и oldest
Методы latest
и oldest
позволяют легко упорядочивать результаты по дате. По умолчанию результат будет упорядочен по столбцу created_at
таблицы. Или вы можете передать имя столбца, по которому вы хотите упорядочить:
$user = DB::table('users') ->latest() ->first();
Метод inRandomOrder
может быть использован для случайной сортировки результатов запроса. Например, вы можете использовать этот метод, чтобы получить случайного пользователя:
$randomUser = DB::table('users') ->inRandomOrder() ->first();
Метод reorder
удаляет все предыдущие "order by" условия, которые ранее были применены к запросу:
$query = DB::table('users')->orderBy('name'); $unorderedUsers = $query->reorder()->get();
Вы можете передать столбец и направление при вызове метода reorder
, чтобы удалить все существующие условия "order by" и применить к запросу совершенно новый порядок:
$query = DB::table('users')->orderBy('name'); $usersOrderedByEmail = $query->reorder('email', 'desc')->get();
groupBy
и having
Как вы могли бы ожидать, методы groupBy
и having
могут быть использованы для группировки результатов запроса. Сигнатура метода having
аналогична сигнатуре метода where
:
$users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get();
Вы можете использовать метод havingBetween
для фильтрации результатов в заданном диапазоне:
$report = DB::table('orders') ->selectRaw('count(id) as number_of_orders, customer_id') ->groupBy('customer_id') ->havingBetween('number_of_orders', [5, 15]) ->get();
Вы можете передать несколько аргументов методу groupBy
, чтобы группировать по нескольким столбцам:
$users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get();
Для создания более сложных выражений having
см. метод havingRaw
.
skip
и take
Вы можете использовать методы skip
и take
для ограничения количества результатов, возвращаемых запросом, или для пропуска заданного числа результатов в запросе:
$users = DB::table('users')->skip(10)->take(5)->get();
В качестве альтернативы вы можете использовать методы limit
и offset
. Эти методы функционально эквивалентны методам take
и skip
соответственно:
$users = DB::table('users') ->offset(10) ->limit(5) ->get();
Иногда вам может потребоваться, чтобы некоторые условия запроса применялись в зависимости от другого условия. Например, вам может потребоваться применить оператор where
только в том случае, если задано определенное значение входного параметра HTTP-запроса. Вы можете сделать это с использованием метода when
:
$role = $request->string('role'); $users = DB::table('users') ->when($role, function (Builder $query, string $role) { $query->where('role_id', $role); }) ->get();
Метод when
выполняет переданное замыкание только в том случае, если первый аргумент равен true
. Если первый аргумент равен false
, замыкание не будет выполнено. Таким образом, в приведенном выше примере замыкание, переданное методу when
, будет вызвано только в том случае, если поле role
присутствует во входящем запросе и оценивается как true
.
Вы можете передать другое замыкание в качестве третьего аргумента методу when
. Это замыкание будет выполнено только в том случае, если первый аргумент оценивается как false
. Для иллюстрации того, как можно использовать эту функцию, мы будем использовать ее для настройки сортировки запроса по умолчанию:
$sortByVotes = $request->boolean('sort_by_votes'); $users = DB::table('users') ->when($sortByVotes, function (Builder $query, bool $sortByVotes) { $query->orderBy('votes'); }, function (Builder $query) { $query->orderBy('name'); }) ->get();
Поставщик запросов также предоставляет метод insert
, который можно использовать для вставки записей в таблицу базы данных. Метод insert
принимает массив названий столбцов и значений:
DB::table('users')->insert([ 'votes' => 0]);
Вы можете вставить несколько записей сразу, передав массив массивов. Каждый массив представляет собой запись, которую следует вставить в таблицу:
DB::table('users')->insert([]);
Метод insertOrIgnore
будет игнорировать ошибки при вставке записей в базу данных. Используя этот метод, вы должны знать, что ошибки дублирования записей будут проигнорированы, а другие типы ошибок также могут быть проигнорированы в зависимости от используемого движка базы данных. Например, insertOrIgnore
будет обходить строгий режим MySQL:
DB::table('users')->insertOrIgnore([]);
Метод insertUsing
вставит новые записи в таблицу, используя подзапрос для определения данных, которые следует вставить:
DB::table('pruned_users')->insertUsing([ 'id', 'name', 'email', 'email_verified_at'], DB::table('users')->select( 'id', 'name', 'email', 'email_verified_at')->where('updated_at', '<=', now()->subMonth()));
Если таблица имеет автоинкрементный идентификатор, используйте метод insertGetId
для вставки записи и получения затем идентификатора:
$id = DB::table('users')->insertGetId();
Внимание При использовании PostgreSQL метод
insertGetId
ожидает, что автоинкрементный столбец будет названid
. Если вы хотите извлечь ID из другой "последовательности", вы можете передать имя столбца вторым параметром методуinsertGetId
.
Метод upsert
вставляет записи, которых не существует, и обновляет записи, которые уже существуют, новыми значениями, которые вы можете указать. Первый аргумент метода состоит из значений для вставки или обновления, в то время как второй аргумент перечисляет столбцы, которые уникальным образом идентифицируют записи в связанной таблице. Третий и последний аргумент метода - это массив столбцов, которые должны быть обновлены, если соответствующая запись уже существует в базе данных:
DB::table('flights')->upsert( [ ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150] ], ['departure', 'destination'], ['price']);
В приведенном выше примере Laravel попытается вставить две записи. Если запись уже существует с теми же значениями столбцов departure
и destination
, Laravel обновит столбец price
этой записи.
Внимание Все базы данных, кроме SQL Server, требуют, чтобы столбцы второго аргумента метода
upsert
имели индекс "первичный" или "уникальный". Кроме того, драйвер базы данных MySQL игнорирует второй аргумент методаupsert
и всегда использует индексы "первичный" и "уникальный" таблицы для обнаружения существующих записей.
Помимо вставки записей в базу данных, Конструктор запросов также может обновлять существующие записи с использованием метода update
. Метод update
, как и метод insert
, принимает массив пар столбец-значение, указывающих столбцы для обновления. Метод update
возвращает количество затронутых строк. Вы можете ограничить запрос update
с использованием условий where
:
$affected = DB::table('users') ->where('id', 1) ->update(['votes' => 1]);
Иногда вам может потребоваться обновить существующую запись в базе данных или создать ее, если соответствующей записи не существует. В этом случае можно использовать метод updateOrInsert
. Метод updateOrInsert
принимает два аргумента: массив условий, по которым будет найдена запись, и массив пар столбец-значение, указывающих столбцы для обновления.
Метод updateOrInsert
попытается найти соответствующую запись в базе данных, используя пары столбец-значение первого аргумента. Если запись существует, она будет обновлена значениями второго аргумента. Если запись не может быть найдена, будет вставлена новая запись со слиянием атрибутов обоих аргументов:
DB::table('users') ->updateOrInsert( ['votes' => '2'] );
При обновлении JSON-столбца вы должны использовать синтаксис ->
для обновления соответствующего ключа в JSON-объекте. Эта операция поддерживается в MySQL 5.7+ и PostgreSQL 9.5+:
$affected = DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]);
Конструктор запросов также предоставляет удобные методы для увеличения или уменьшения значения заданного столбца. Оба этих метода принимают как минимум один аргумент: столбец для модификации. Второй аргумент может быть предоставлен для указания суммы, на которую следует увеличить или уменьшить столбец:
DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5);
При необходимости вы также можете указать дополнительные столбцы для обновления во время операции увеличения или уменьшения:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
Кроме того, вы можете увеличивать или уменьшать значения нескольких столбцов одновременно с использованием методов incrementEach
и decrementEach
:
DB::table('users')->incrementEach([ 'votes' => 5, 'balance' => 100,]);
Метод delete
построителя запросов может быть использован для удаления записей из таблицы. Метод delete
возвращает количество затронутых строк. Вы можете ограничить операторы delete
, добавив условия "where" перед вызовом метода delete
:
$deleted = DB::table('users')->delete(); $deleted = DB::table('users')->where('votes', '>', 100)->delete();
Если вы хотите усечь всю таблицу, удалив все записи из таблицы и сбросив автоматическое инкрементирование идентификатора на ноль, вы можете использовать метод truncate
:
DB::table('users')->truncate();
При усечении базы данных PostgreSQL применяется поведение CASCADE
. Это означает, что будут удалены все записи, связанные с внешним ключом в других таблицах.
Кроме того, Конструктор запросов включает несколько функций для реализации "пессимистической блокировки" при выполнении ваших операторов select
. Для выполнения оператора с "разделяемой блокировкой" вы можете вызвать метод sharedLock
. Разделяемая блокировка предотвращает изменение выбранных строк до фиксации вашей транзакции:
DB::table('users') ->where('votes', '>', 100) ->sharedLock() ->get();
В качестве альтернативы можно использовать метод lockForUpdate
. Блокировка "for update" предотвращает изменение выбранных записей или их выбор с другой разделяемой блокировкой:
DB::table('users') ->where('votes', '>', 100) ->lockForUpdate() ->get();
Вы можете использовать методы dd
и dump
при построении запроса для вывода текущих привязок и SQL-запроса. Метод dd
отобразит отладочную информацию и затем остановит выполнение запроса. Метод dump
отобразит отладочную информацию, но позволит выполнению запроса продолжиться:
DB::table('users')->where('votes', '>', 100)->dd(); DB::table('users')->where('votes', '>', 100)->dump();
Методы dumpRawSql
и ddRawSql
могут быть вызваны для вывода SQL-запроса с правильно подставленными всеми параметрами привязки:
DB::table('users')->where('votes', '>', 100)->dumpRawSql(); DB::table('users')->where('votes', '>', 100)->ddRawSql();