Документация Laravel 10.x
Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.
Конструктор запросов к базе данных Laravel предоставляет удобный, плавный интерфейс для создания и выполнения запросов к базе данных. Его можно использовать для выполнения большинства операций с базой данных в вашем приложении и отлично работает с всеми поддерживаемыми системами управления базами данных Laravel.
Конструктор запросов Laravel использует привязку параметров PDO для защиты вашего приложения от атак SQL-инъекций. Нет необходимости очищать или санитаризировать строки, передаваемые построителю запросов, как привязки запросов.
Внимание PDO не поддерживает привязку имен столбцов. Поэтому никогда не допускайте ввод пользовательских данных для определения имен столбцов, на которые ссылаются ваши запросы, включая столбцы "order by".
Вы можете использовать метод table предоставленный фасадом DB для начала запроса. Метод table возвращает экземпляр построителя запросов для данной таблицы, позволяя вам добавлять более многочисленные ограничения к запросу, а затем, наконец, извлекать результаты запроса, используя метод get:
<?phpnamespace 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([ 'email' => '[email protected]', 'votes' => 0]);
Вы можете вставить несколько записей сразу, передав массив массивов. Каждый массив представляет собой запись, которую следует вставить в таблицу:
DB::table('users')->insert([ ['email' => '[email protected]', 'votes' => 0], ['email' => '[email protected]', 'votes' => 0],]);
Метод insertOrIgnore будет игнорировать ошибки при вставке записей в базу данных. Используя этот метод, вы должны знать, что ошибки дублирования записей будут проигнорированы, а другие типы ошибок также могут быть проигнорированы в зависимости от используемого движка базы данных. Например, insertOrIgnore будет обходить строгий режим MySQL:
DB::table('users')->insertOrIgnore([ ['id' => 1, 'email' => '[email protected]'], ['id' => 2, 'email' => '[email protected]'],]);
Метод 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( ['email' => '[email protected]', 'votes' => 0]);
Внимание При использовании 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( ['email' => '[email protected]', 'name' => 'John'], ['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();