3496 lines
82 KiB
Markdown
3496 lines
82 KiB
Markdown
# Database: Query Builder
|
||
|
||
* Introduction
|
||
* Running Database Queries
|
||
* Chunking Results
|
||
* Streaming Results Lazily
|
||
* Aggregates
|
||
* Select Statements
|
||
* Raw Expressions
|
||
* Joins
|
||
* Unions
|
||
* Basic Where Clauses
|
||
* Where Clauses
|
||
* Or Where Clauses
|
||
* Where Not Clauses
|
||
* Where Any / All / None Clauses
|
||
* JSON Where Clauses
|
||
* Additional Where Clauses
|
||
* Logical Grouping
|
||
* Advanced Where Clauses
|
||
* Where Exists Clauses
|
||
* Subquery Where Clauses
|
||
* Full Text Where Clauses
|
||
* Ordering, Grouping, Limit and Offset
|
||
* Ordering
|
||
* Grouping
|
||
* Limit and Offset
|
||
* Conditional Clauses
|
||
* Insert Statements
|
||
* Upserts
|
||
* Update Statements
|
||
* Updating JSON Columns
|
||
* Increment and Decrement
|
||
* Delete Statements
|
||
* Pessimistic Locking
|
||
* Reusable Query Components
|
||
* Debugging
|
||
|
||
## Introduction
|
||
|
||
Laravel's database query builder provides a convenient, fluent interface to
|
||
creating and running database queries. It can be used to perform most database
|
||
operations in your application and works perfectly with all of Laravel's
|
||
supported database systems.
|
||
|
||
The Laravel query builder uses PDO parameter binding to protect your
|
||
application against SQL injection attacks. There is no need to clean or
|
||
sanitize strings passed to the query builder as query bindings.
|
||
|
||
PDO does not support binding column names. Therefore, you should never allow
|
||
user input to dictate the column names referenced by your queries, including
|
||
"order by" columns.
|
||
|
||
## Running Database Queries
|
||
|
||
#### Retrieving All Rows From a Table
|
||
|
||
You may use the `table` method provided by the `DB` facade to begin a query.
|
||
The `table` method returns a fluent query builder instance for the given
|
||
table, allowing you to chain more constraints onto the query and then finally
|
||
retrieve the results of the query using the `get` method:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Http\Controllers;
|
||
|
||
4
|
||
|
||
5use Illuminate\Support\Facades\DB;
|
||
|
||
6use Illuminate\View\View;
|
||
|
||
7
|
||
|
||
8class UserController extends Controller
|
||
|
||
9{
|
||
|
||
10 /**
|
||
|
||
11 * Show a list of all of the application's users.
|
||
|
||
12 */
|
||
|
||
13 public function index(): View
|
||
|
||
14 {
|
||
|
||
15 $users = DB::table('users')->get();
|
||
|
||
16
|
||
|
||
17 return view('user.index', ['users' => $users]);
|
||
|
||
18 }
|
||
|
||
19}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\View\View;
|
||
|
||
class UserController extends Controller
|
||
{
|
||
/**
|
||
* Show a list of all of the application's users.
|
||
*/
|
||
public function index(): View
|
||
{
|
||
$users = DB::table('users')->get();
|
||
|
||
return view('user.index', ['users' => $users]);
|
||
}
|
||
}
|
||
|
||
The `get` method returns an `Illuminate\Support\Collection` instance
|
||
containing the results of the query where each result is an instance of the
|
||
PHP `stdClass` object. You may access each column's value by accessing the
|
||
column as a property of the object:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')->get();
|
||
|
||
4
|
||
|
||
5foreach ($users as $user) {
|
||
|
||
6 echo $user->name;
|
||
|
||
7}
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$users = DB::table('users')->get();
|
||
|
||
foreach ($users as $user) {
|
||
echo $user->name;
|
||
}
|
||
|
||
Laravel collections provide a variety of extremely powerful methods for
|
||
mapping and reducing data. For more information on Laravel collections, check
|
||
out the [collection documentation](/docs/12.x/collections).
|
||
|
||
#### Retrieving a Single Row / Column From a Table
|
||
|
||
If you just need to retrieve a single row from a database table, you may use
|
||
the `DB` facade's `first` method. This method will return a single `stdClass`
|
||
object:
|
||
|
||
|
||
|
||
1$user = DB::table('users')->where('name', 'John')->first();
|
||
|
||
2
|
||
|
||
3return $user->email;
|
||
|
||
|
||
$user = DB::table('users')->where('name', 'John')->first();
|
||
|
||
return $user->email;
|
||
|
||
If you would like to retrieve a single row from a database table, but throw an
|
||
`Illuminate\Database\RecordNotFoundException` if no matching row is found, you
|
||
may use the `firstOrFail` method. If the `RecordNotFoundException` is not
|
||
caught, a 404 HTTP response is automatically sent back to the client:
|
||
|
||
|
||
|
||
1$user = DB::table('users')->where('name', 'John')->firstOrFail();
|
||
|
||
|
||
$user = DB::table('users')->where('name', 'John')->firstOrFail();
|
||
|
||
If you don't need an entire row, you may extract a single value from a record
|
||
using the `value` method. This method will return the value of the column
|
||
directly:
|
||
|
||
|
||
|
||
1$email = DB::table('users')->where('name', 'John')->value('email');
|
||
|
||
|
||
$email = DB::table('users')->where('name', 'John')->value('email');
|
||
|
||
To retrieve a single row by its `id` column value, use the `find` method:
|
||
|
||
|
||
|
||
1$user = DB::table('users')->find(3);
|
||
|
||
|
||
$user = DB::table('users')->find(3);
|
||
|
||
#### Retrieving a List of Column Values
|
||
|
||
If you would like to retrieve an `Illuminate\Support\Collection` instance
|
||
containing the values of a single column, you may use the `pluck` method. In
|
||
this example, we'll retrieve a collection of user titles:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$titles = DB::table('users')->pluck('title');
|
||
|
||
4
|
||
|
||
5foreach ($titles as $title) {
|
||
|
||
6 echo $title;
|
||
|
||
7}
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$titles = DB::table('users')->pluck('title');
|
||
|
||
foreach ($titles as $title) {
|
||
echo $title;
|
||
}
|
||
|
||
You may specify the column that the resulting collection should use as its
|
||
keys by providing a second argument to the `pluck` method:
|
||
|
||
|
||
|
||
1$titles = DB::table('users')->pluck('title', 'name');
|
||
|
||
2
|
||
|
||
3foreach ($titles as $name => $title) {
|
||
|
||
4 echo $title;
|
||
|
||
5}
|
||
|
||
|
||
$titles = DB::table('users')->pluck('title', 'name');
|
||
|
||
foreach ($titles as $name => $title) {
|
||
echo $title;
|
||
}
|
||
|
||
### Chunking Results
|
||
|
||
If you need to work with thousands of database records, consider using the
|
||
`chunk` method provided by the `DB` facade. This method retrieves a small
|
||
chunk of results at a time and feeds each chunk into a closure for processing.
|
||
For example, let's retrieve the entire `users` table in chunks of 100 records
|
||
at a time:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Collection;
|
||
|
||
2use Illuminate\Support\Facades\DB;
|
||
|
||
3
|
||
|
||
4DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
|
||
|
||
5 foreach ($users as $user) {
|
||
|
||
6 // ...
|
||
|
||
7 }
|
||
|
||
8});
|
||
|
||
|
||
use Illuminate\Support\Collection;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
|
||
foreach ($users as $user) {
|
||
// ...
|
||
}
|
||
});
|
||
|
||
You may stop further chunks from being processed by returning `false` from the
|
||
closure:
|
||
|
||
|
||
|
||
1DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
|
||
|
||
2 // Process the records...
|
||
|
||
3
|
||
|
||
4 return false;
|
||
|
||
5});
|
||
|
||
|
||
DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) {
|
||
// Process the records...
|
||
|
||
return false;
|
||
});
|
||
|
||
If you are updating database records while chunking results, your chunk
|
||
results could change in unexpected ways. If you plan to update the retrieved
|
||
records while chunking, it is always best to use the `chunkById` method
|
||
instead. This method will automatically paginate the results based on the
|
||
record's primary key:
|
||
|
||
|
||
|
||
1DB::table('users')->where('active', false)
|
||
|
||
2 ->chunkById(100, function (Collection $users) {
|
||
|
||
3 foreach ($users as $user) {
|
||
|
||
4 DB::table('users')
|
||
|
||
5 ->where('id', $user->id)
|
||
|
||
6 ->update(['active' => true]);
|
||
|
||
7 }
|
||
|
||
8 });
|
||
|
||
|
||
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]);
|
||
}
|
||
});
|
||
|
||
Since the `chunkById` and `lazyById` methods add their own "where" conditions
|
||
to the query being executed, you should typically logically group your own
|
||
conditions within a closure:
|
||
|
||
|
||
|
||
1DB::table('users')->where(function ($query) {
|
||
|
||
2 $query->where('credits', 1)->orWhere('credits', 2);
|
||
|
||
3})->chunkById(100, function (Collection $users) {
|
||
|
||
4 foreach ($users as $user) {
|
||
|
||
5 DB::table('users')
|
||
|
||
6 ->where('id', $user->id)
|
||
|
||
7 ->update(['credits' => 3]);
|
||
|
||
8 }
|
||
|
||
9});
|
||
|
||
|
||
DB::table('users')->where(function ($query) {
|
||
$query->where('credits', 1)->orWhere('credits', 2);
|
||
})->chunkById(100, function (Collection $users) {
|
||
foreach ($users as $user) {
|
||
DB::table('users')
|
||
->where('id', $user->id)
|
||
->update(['credits' => 3]);
|
||
}
|
||
});
|
||
|
||
When updating or deleting records inside the chunk callback, any changes to
|
||
the primary key or foreign keys could affect the chunk query. This could
|
||
potentially result in records not being included in the chunked results.
|
||
|
||
### Streaming Results Lazily
|
||
|
||
The `lazy` method works similarly to the chunk method in the sense that it
|
||
executes the query in chunks. However, instead of passing each chunk into a
|
||
callback, the `lazy()` method returns a
|
||
[LazyCollection](/docs/12.x/collections#lazy-collections), which lets you
|
||
interact with the results as a single stream:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3DB::table('users')->orderBy('id')->lazy()->each(function (object $user) {
|
||
|
||
4 // ...
|
||
|
||
5});
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
DB::table('users')->orderBy('id')->lazy()->each(function (object $user) {
|
||
// ...
|
||
});
|
||
|
||
Once again, if you plan to update the retrieved records while iterating over
|
||
them, it is best to use the `lazyById` or `lazyByIdDesc` methods instead.
|
||
These methods will automatically paginate the results based on the record's
|
||
primary key:
|
||
|
||
|
||
|
||
1DB::table('users')->where('active', false)
|
||
|
||
2 ->lazyById()->each(function (object $user) {
|
||
|
||
3 DB::table('users')
|
||
|
||
4 ->where('id', $user->id)
|
||
|
||
5 ->update(['active' => true]);
|
||
|
||
6 });
|
||
|
||
|
||
DB::table('users')->where('active', false)
|
||
->lazyById()->each(function (object $user) {
|
||
DB::table('users')
|
||
->where('id', $user->id)
|
||
->update(['active' => true]);
|
||
});
|
||
|
||
When updating or deleting records while iterating over them, any changes to
|
||
the primary key or foreign keys could affect the chunk query. This could
|
||
potentially result in records not being included in the results.
|
||
|
||
### Aggregates
|
||
|
||
The query builder also provides a variety of methods for retrieving aggregate
|
||
values like `count`, `max`, `min`, `avg`, and `sum`. You may call any of these
|
||
methods after constructing your query:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')->count();
|
||
|
||
4
|
||
|
||
5$price = DB::table('orders')->max('price');
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$users = DB::table('users')->count();
|
||
|
||
$price = DB::table('orders')->max('price');
|
||
|
||
Of course, you may combine these methods with other clauses to fine-tune how
|
||
your aggregate value is calculated:
|
||
|
||
|
||
|
||
1$price = DB::table('orders')
|
||
|
||
2 ->where('finalized', 1)
|
||
|
||
3 ->avg('price');
|
||
|
||
|
||
$price = DB::table('orders')
|
||
->where('finalized', 1)
|
||
->avg('price');
|
||
|
||
#### Determining if Records Exist
|
||
|
||
Instead of using the `count` method to determine if any records exist that
|
||
match your query's constraints, you may use the `exists` and `doesntExist`
|
||
methods:
|
||
|
||
|
||
|
||
1if (DB::table('orders')->where('finalized', 1)->exists()) {
|
||
|
||
2 // ...
|
||
|
||
3}
|
||
|
||
4
|
||
|
||
5if (DB::table('orders')->where('finalized', 1)->doesntExist()) {
|
||
|
||
6 // ...
|
||
|
||
7}
|
||
|
||
|
||
if (DB::table('orders')->where('finalized', 1)->exists()) {
|
||
// ...
|
||
}
|
||
|
||
if (DB::table('orders')->where('finalized', 1)->doesntExist()) {
|
||
// ...
|
||
}
|
||
|
||
## Select Statements
|
||
|
||
#### Specifying a Select Clause
|
||
|
||
You may not always want to select all columns from a database table. Using the
|
||
`select` method, you can specify a custom "select" clause for the query:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')
|
||
|
||
4 ->select('name', 'email as user_email')
|
||
|
||
5 ->get();
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$users = DB::table('users')
|
||
->select('name', 'email as user_email')
|
||
->get();
|
||
|
||
The `distinct` method allows you to force the query to return distinct
|
||
results:
|
||
|
||
|
||
|
||
1$users = DB::table('users')->distinct()->get();
|
||
|
||
|
||
$users = DB::table('users')->distinct()->get();
|
||
|
||
If you already have a query builder instance and you wish to add a column to
|
||
its existing select clause, you may use the `addSelect` method:
|
||
|
||
|
||
|
||
1$query = DB::table('users')->select('name');
|
||
|
||
2
|
||
|
||
3$users = $query->addSelect('age')->get();
|
||
|
||
|
||
$query = DB::table('users')->select('name');
|
||
|
||
$users = $query->addSelect('age')->get();
|
||
|
||
## Raw Expressions
|
||
|
||
Sometimes you may need to insert an arbitrary string into a query. To create a
|
||
raw string expression, you may use the `raw` method provided by the `DB`
|
||
facade:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->select(DB::raw('count(*) as user_count, status'))
|
||
|
||
3 ->where('status', '<>', 1)
|
||
|
||
4 ->groupBy('status')
|
||
|
||
5 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->select(DB::raw('count(*) as user_count, status'))
|
||
->where('status', '<>', 1)
|
||
->groupBy('status')
|
||
->get();
|
||
|
||
Raw statements will be injected into the query as strings, so you should be
|
||
extremely careful to avoid creating SQL injection vulnerabilities.
|
||
|
||
### Raw Methods
|
||
|
||
Instead of using the `DB::raw` method, you may also use the following methods
|
||
to insert a raw expression into various parts of your query. **Remember,
|
||
Laravel cannot guarantee that any query using raw expressions is protected
|
||
against SQL injection vulnerabilities.**
|
||
|
||
#### `selectRaw`
|
||
|
||
The `selectRaw` method can be used in place of `addSelect(DB::raw(/* ...
|
||
*/))`. This method accepts an optional array of bindings as its second
|
||
argument:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->selectRaw('price * ? as price_with_tax', [1.0825])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->selectRaw('price * ? as price_with_tax', [1.0825])
|
||
->get();
|
||
|
||
#### `whereRaw / orWhereRaw`
|
||
|
||
The `whereRaw` and `orWhereRaw` methods can be used to inject a raw "where"
|
||
clause into your query. These methods accept an optional array of bindings as
|
||
their second argument:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
|
||
->get();
|
||
|
||
#### `havingRaw / orHavingRaw`
|
||
|
||
The `havingRaw` and `orHavingRaw` methods may be used to provide a raw string
|
||
as the value of the "having" clause. These methods accept an optional array of
|
||
bindings as their second argument:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->select('department', DB::raw('SUM(price) as total_sales'))
|
||
|
||
3 ->groupBy('department')
|
||
|
||
4 ->havingRaw('SUM(price) > ?', [2500])
|
||
|
||
5 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->select('department', DB::raw('SUM(price) as total_sales'))
|
||
->groupBy('department')
|
||
->havingRaw('SUM(price) > ?', [2500])
|
||
->get();
|
||
|
||
#### `orderByRaw`
|
||
|
||
The `orderByRaw` method may be used to provide a raw string as the value of
|
||
the "order by" clause:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->orderByRaw('updated_at - created_at DESC')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->orderByRaw('updated_at - created_at DESC')
|
||
->get();
|
||
|
||
### `groupByRaw`
|
||
|
||
The `groupByRaw` method may be used to provide a raw string as the value of
|
||
the `group by` clause:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->select('city', 'state')
|
||
|
||
3 ->groupByRaw('city, state')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->select('city', 'state')
|
||
->groupByRaw('city, state')
|
||
->get();
|
||
|
||
## Joins
|
||
|
||
#### Inner Join Clause
|
||
|
||
The query builder may also be used to add join clauses to your queries. To
|
||
perform a basic "inner join", you may use the `join` method on a query builder
|
||
instance. The first argument passed to the `join` method is the name of the
|
||
table you need to join to, while the remaining arguments specify the column
|
||
constraints for the join. You may even join multiple tables in a single query:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')
|
||
|
||
4 ->join('contacts', 'users.id', '=', 'contacts.user_id')
|
||
|
||
5 ->join('orders', 'users.id', '=', 'orders.user_id')
|
||
|
||
6 ->select('users.*', 'contacts.phone', 'orders.price')
|
||
|
||
7 ->get();
|
||
|
||
|
||
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 Clause
|
||
|
||
If you would like to perform a "left join" or "right join" instead of an
|
||
"inner join", use the `leftJoin` or `rightJoin` methods. These methods have
|
||
the same signature as the `join` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->rightJoin('posts', 'users.id', '=', 'posts.user_id')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->rightJoin('posts', 'users.id', '=', 'posts.user_id')
|
||
->get();
|
||
|
||
#### Cross Join Clause
|
||
|
||
You may use the `crossJoin` method to perform a "cross join". Cross joins
|
||
generate a cartesian product between the first table and the joined table:
|
||
|
||
|
||
|
||
1$sizes = DB::table('sizes')
|
||
|
||
2 ->crossJoin('colors')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$sizes = DB::table('sizes')
|
||
->crossJoin('colors')
|
||
->get();
|
||
|
||
#### Advanced Join Clauses
|
||
|
||
You may also specify more advanced join clauses. To get started, pass a
|
||
closure as the second argument to the `join` method. The closure will receive
|
||
a `Illuminate\Database\Query\JoinClause` instance which allows you to specify
|
||
constraints on the "join" clause:
|
||
|
||
|
||
|
||
1DB::table('users')
|
||
|
||
2 ->join('contacts', function (JoinClause $join) {
|
||
|
||
3 $join->on('users.id', '=', 'contacts.user_id')->orOn(/* ... */);
|
||
|
||
4 })
|
||
|
||
5 ->get();
|
||
|
||
|
||
DB::table('users')
|
||
->join('contacts', function (JoinClause $join) {
|
||
$join->on('users.id', '=', 'contacts.user_id')->orOn(/* ... */);
|
||
})
|
||
->get();
|
||
|
||
If you would like to use a "where" clause on your joins, you may use the
|
||
`where` and `orWhere` methods provided by the `JoinClause` instance. Instead
|
||
of comparing two columns, these methods will compare the column against a
|
||
value:
|
||
|
||
|
||
|
||
1DB::table('users')
|
||
|
||
2 ->join('contacts', function (JoinClause $join) {
|
||
|
||
3 $join->on('users.id', '=', 'contacts.user_id')
|
||
|
||
4 ->where('contacts.user_id', '>', 5);
|
||
|
||
5 })
|
||
|
||
6 ->get();
|
||
|
||
|
||
DB::table('users')
|
||
->join('contacts', function (JoinClause $join) {
|
||
$join->on('users.id', '=', 'contacts.user_id')
|
||
->where('contacts.user_id', '>', 5);
|
||
})
|
||
->get();
|
||
|
||
#### Subquery Joins
|
||
|
||
You may use the `joinSub`, `leftJoinSub`, and `rightJoinSub` methods to join a
|
||
query to a subquery. Each of these methods receives three arguments: the
|
||
subquery, its table alias, and a closure that defines the related columns. In
|
||
this example, we will retrieve a collection of users where each user record
|
||
also contains the `created_at` timestamp of the user's most recently published
|
||
blog post:
|
||
|
||
|
||
|
||
1$latestPosts = DB::table('posts')
|
||
|
||
2 ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
|
||
|
||
3 ->where('is_published', true)
|
||
|
||
4 ->groupBy('user_id');
|
||
|
||
5
|
||
|
||
6$users = DB::table('users')
|
||
|
||
7 ->joinSub($latestPosts, 'latest_posts', function (JoinClause $join) {
|
||
|
||
8 $join->on('users.id', '=', 'latest_posts.user_id');
|
||
|
||
9 })->get();
|
||
|
||
|
||
$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();
|
||
|
||
#### Lateral Joins
|
||
|
||
Lateral joins are currently supported by PostgreSQL, MySQL >= 8.0.14, and SQL
|
||
Server.
|
||
|
||
You may use the `joinLateral` and `leftJoinLateral` methods to perform a
|
||
"lateral join" with a subquery. Each of these methods receives two arguments:
|
||
the subquery and its table alias. The join condition(s) should be specified
|
||
within the `where` clause of the given subquery. Lateral joins are evaluated
|
||
for each row and can reference columns outside the subquery.
|
||
|
||
In this example, we will retrieve a collection of users as well as the user's
|
||
three most recent blog posts. Each user can produce up to three rows in the
|
||
result set: one for each of their most recent blog posts. The join condition
|
||
is specified with a `whereColumn` clause within the subquery, referencing the
|
||
current user row:
|
||
|
||
|
||
|
||
1$latestPosts = DB::table('posts')
|
||
|
||
2 ->select('id as post_id', 'title as post_title', 'created_at as post_created_at')
|
||
|
||
3 ->whereColumn('user_id', 'users.id')
|
||
|
||
4 ->orderBy('created_at', 'desc')
|
||
|
||
5 ->limit(3);
|
||
|
||
6
|
||
|
||
7$users = DB::table('users')
|
||
|
||
8 ->joinLateral($latestPosts, 'latest_posts')
|
||
|
||
9 ->get();
|
||
|
||
|
||
$latestPosts = DB::table('posts')
|
||
->select('id as post_id', 'title as post_title', 'created_at as post_created_at')
|
||
->whereColumn('user_id', 'users.id')
|
||
->orderBy('created_at', 'desc')
|
||
->limit(3);
|
||
|
||
$users = DB::table('users')
|
||
->joinLateral($latestPosts, 'latest_posts')
|
||
->get();
|
||
|
||
## Unions
|
||
|
||
The query builder also provides a convenient method to "union" two or more
|
||
queries together. For example, you may create an initial query and use the
|
||
`union` method to union it with more queries:
|
||
|
||
|
||
|
||
1use Illuminate\Support\Facades\DB;
|
||
|
||
2
|
||
|
||
3$first = DB::table('users')
|
||
|
||
4 ->whereNull('first_name');
|
||
|
||
5
|
||
|
||
6$users = DB::table('users')
|
||
|
||
7 ->whereNull('last_name')
|
||
|
||
8 ->union($first)
|
||
|
||
9 ->get();
|
||
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$first = DB::table('users')
|
||
->whereNull('first_name');
|
||
|
||
$users = DB::table('users')
|
||
->whereNull('last_name')
|
||
->union($first)
|
||
->get();
|
||
|
||
In addition to the `union` method, the query builder provides a `unionAll`
|
||
method. Queries that are combined using the `unionAll` method will not have
|
||
their duplicate results removed. The `unionAll` method has the same method
|
||
signature as the `union` method.
|
||
|
||
## Basic Where Clauses
|
||
|
||
### Where Clauses
|
||
|
||
You may use the query builder's `where` method to add "where" clauses to the
|
||
query. The most basic call to the `where` method requires three arguments. The
|
||
first argument is the name of the column. The second argument is an operator,
|
||
which can be any of the database's supported operators. The third argument is
|
||
the value to compare against the column's value.
|
||
|
||
For example, the following query retrieves users where the value of the
|
||
`votes` column is equal to `100` and the value of the `age` column is greater
|
||
than `35`:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('votes', '=', 100)
|
||
|
||
3 ->where('age', '>', 35)
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('votes', '=', 100)
|
||
->where('age', '>', 35)
|
||
->get();
|
||
|
||
For convenience, if you want to verify that a column is `=` to a given value,
|
||
you may pass the value as the second argument to the `where` method. Laravel
|
||
will assume you would like to use the `=` operator:
|
||
|
||
|
||
|
||
1$users = DB::table('users')->where('votes', 100)->get();
|
||
|
||
|
||
$users = DB::table('users')->where('votes', 100)->get();
|
||
|
||
You may also provide an associative array to the `where` method to quickly
|
||
query against multiple columns:
|
||
|
||
|
||
|
||
1$users = DB::table('users')->where([
|
||
|
||
2 'first_name' => 'Jane',
|
||
|
||
3 'last_name' => 'Doe',
|
||
|
||
4])->get();
|
||
|
||
|
||
$users = DB::table('users')->where([
|
||
'first_name' => 'Jane',
|
||
'last_name' => 'Doe',
|
||
])->get();
|
||
|
||
As previously mentioned, you may use any operator that is supported by your
|
||
database system:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('votes', '>=', 100)
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->where('votes', '<>', 100)
|
||
|
||
7 ->get();
|
||
|
||
8
|
||
|
||
9$users = DB::table('users')
|
||
|
||
10 ->where('name', 'like', 'T%')
|
||
|
||
11 ->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();
|
||
|
||
You may also pass an array of conditions to the `where` function. Each element
|
||
of the array should be an array containing the three arguments typically
|
||
passed to the `where` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')->where([
|
||
|
||
2 ['status', '=', '1'],
|
||
|
||
3 ['subscribed', '<>', '1'],
|
||
|
||
4])->get();
|
||
|
||
|
||
$users = DB::table('users')->where([
|
||
['status', '=', '1'],
|
||
['subscribed', '<>', '1'],
|
||
])->get();
|
||
|
||
PDO does not support binding column names. Therefore, you should never allow
|
||
user input to dictate the column names referenced by your queries, including
|
||
"order by" columns.
|
||
|
||
MySQL and MariaDB automatically typecast strings to integers in string-number
|
||
comparisons. In this process, non-numeric strings are converted to `0`, which
|
||
can lead to unexpected results. For example, if your table has a `secret`
|
||
column with a value of `aaa` and you run `User::where('secret', 0)`, that row
|
||
will be returned. To avoid this, ensure all values are typecast to their
|
||
appropriate types before using them in queries.
|
||
|
||
### Or Where Clauses
|
||
|
||
When chaining together calls to the query builder's `where` method, the
|
||
"where" clauses will be joined together using the `and` operator. However, you
|
||
may use the `orWhere` method to join a clause to the query using the `or`
|
||
operator. The `orWhere` method accepts the same arguments as the `where`
|
||
method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('votes', '>', 100)
|
||
|
||
3 ->orWhere('name', 'John')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->orWhere('name', 'John')
|
||
->get();
|
||
|
||
If you need to group an "or" condition within parentheses, you may pass a
|
||
closure as the first argument to the `orWhere` method:
|
||
|
||
|
||
|
||
1use Illuminate\Database\Query\Builder;
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')
|
||
|
||
4 ->where('votes', '>', 100)
|
||
|
||
5 ->orWhere(function (Builder $query) {
|
||
|
||
6 $query->where('name', 'Abigail')
|
||
|
||
7 ->where('votes', '>', 50);
|
||
|
||
8 })
|
||
|
||
9 ->get();
|
||
|
||
|
||
use Illuminate\Database\Query\Builder;
|
||
|
||
$users = DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->orWhere(function (Builder $query) {
|
||
$query->where('name', 'Abigail')
|
||
->where('votes', '>', 50);
|
||
})
|
||
->get();
|
||
|
||
The example above will produce the following SQL:
|
||
|
||
|
||
|
||
1select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
|
||
|
||
|
||
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
|
||
|
||
You should always group `orWhere` calls in order to avoid unexpected behavior
|
||
when global scopes are applied.
|
||
|
||
### Where Not Clauses
|
||
|
||
The `whereNot` and `orWhereNot` methods may be used to negate a given group of
|
||
query constraints. For example, the following query excludes products that are
|
||
on clearance or which have a price that is less than ten:
|
||
|
||
|
||
|
||
1$products = DB::table('products')
|
||
|
||
2 ->whereNot(function (Builder $query) {
|
||
|
||
3 $query->where('clearance', true)
|
||
|
||
4 ->orWhere('price', '<', 10);
|
||
|
||
5 })
|
||
|
||
6 ->get();
|
||
|
||
|
||
$products = DB::table('products')
|
||
->whereNot(function (Builder $query) {
|
||
$query->where('clearance', true)
|
||
->orWhere('price', '<', 10);
|
||
})
|
||
->get();
|
||
|
||
### Where Any / All / None Clauses
|
||
|
||
Sometimes you may need to apply the same query constraints to multiple
|
||
columns. For example, you may want to retrieve all records where any columns
|
||
in a given list are `LIKE` a given value. You may accomplish this using the
|
||
`whereAny` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('active', true)
|
||
|
||
3 ->whereAny([
|
||
|
||
4 'name',
|
||
|
||
5 'email',
|
||
|
||
6 'phone',
|
||
|
||
7 ], 'like', 'Example%')
|
||
|
||
8 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('active', true)
|
||
->whereAny([
|
||
'name',
|
||
'email',
|
||
'phone',
|
||
], 'like', 'Example%')
|
||
->get();
|
||
|
||
The query above will result in the following SQL:
|
||
|
||
|
||
|
||
1SELECT *
|
||
|
||
2FROM users
|
||
|
||
3WHERE active = true AND (
|
||
|
||
4 name LIKE 'Example%' OR
|
||
|
||
5 email LIKE 'Example%' OR
|
||
|
||
6 phone LIKE 'Example%'
|
||
|
||
7)
|
||
|
||
|
||
SELECT *
|
||
FROM users
|
||
WHERE active = true AND (
|
||
name LIKE 'Example%' OR
|
||
email LIKE 'Example%' OR
|
||
phone LIKE 'Example%'
|
||
)
|
||
|
||
Similarly, the `whereAll` method may be used to retrieve records where all of
|
||
the given columns match a given constraint:
|
||
|
||
|
||
|
||
1$posts = DB::table('posts')
|
||
|
||
2 ->where('published', true)
|
||
|
||
3 ->whereAll([
|
||
|
||
4 'title',
|
||
|
||
5 'content',
|
||
|
||
6 ], 'like', '%Laravel%')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$posts = DB::table('posts')
|
||
->where('published', true)
|
||
->whereAll([
|
||
'title',
|
||
'content',
|
||
], 'like', '%Laravel%')
|
||
->get();
|
||
|
||
The query above will result in the following SQL:
|
||
|
||
|
||
|
||
1SELECT *
|
||
|
||
2FROM posts
|
||
|
||
3WHERE published = true AND (
|
||
|
||
4 title LIKE '%Laravel%' AND
|
||
|
||
5 content LIKE '%Laravel%'
|
||
|
||
6)
|
||
|
||
|
||
SELECT *
|
||
FROM posts
|
||
WHERE published = true AND (
|
||
title LIKE '%Laravel%' AND
|
||
content LIKE '%Laravel%'
|
||
)
|
||
|
||
The `whereNone` method may be used to retrieve records where none of the given
|
||
columns match a given constraint:
|
||
|
||
|
||
|
||
1$posts = DB::table('albums')
|
||
|
||
2 ->where('published', true)
|
||
|
||
3 ->whereNone([
|
||
|
||
4 'title',
|
||
|
||
5 'lyrics',
|
||
|
||
6 'tags',
|
||
|
||
7 ], 'like', '%explicit%')
|
||
|
||
8 ->get();
|
||
|
||
|
||
$posts = DB::table('albums')
|
||
->where('published', true)
|
||
->whereNone([
|
||
'title',
|
||
'lyrics',
|
||
'tags',
|
||
], 'like', '%explicit%')
|
||
->get();
|
||
|
||
The query above will result in the following SQL:
|
||
|
||
|
||
|
||
1SELECT *
|
||
|
||
2FROM albums
|
||
|
||
3WHERE published = true AND NOT (
|
||
|
||
4 title LIKE '%explicit%' OR
|
||
|
||
5 lyrics LIKE '%explicit%' OR
|
||
|
||
6 tags LIKE '%explicit%'
|
||
|
||
7)
|
||
|
||
|
||
SELECT *
|
||
FROM albums
|
||
WHERE published = true AND NOT (
|
||
title LIKE '%explicit%' OR
|
||
lyrics LIKE '%explicit%' OR
|
||
tags LIKE '%explicit%'
|
||
)
|
||
|
||
### JSON Where Clauses
|
||
|
||
Laravel also supports querying JSON column types on databases that provide
|
||
support for JSON column types. Currently, this includes MariaDB 10.3+, MySQL
|
||
8.0+, PostgreSQL 12.0+, SQL Server 2017+, and SQLite 3.39.0+. To query a JSON
|
||
column, use the `->` operator:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('preferences->dining->meal', 'salad')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereIn('preferences->dining->meal', ['pasta', 'salad', 'sandwiches'])
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('preferences->dining->meal', 'salad')
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->whereIn('preferences->dining->meal', ['pasta', 'salad', 'sandwiches'])
|
||
->get();
|
||
|
||
You may use the `whereJsonContains` and `whereJsonDoesntContain` methods to
|
||
query JSON arrays:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereJsonContains('options->languages', 'en')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereJsonDoesntContain('options->languages', 'en')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonContains('options->languages', 'en')
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonDoesntContain('options->languages', 'en')
|
||
->get();
|
||
|
||
If your application uses the MariaDB, MySQL, or PostgreSQL databases, you may
|
||
pass an array of values to the `whereJsonContains` and
|
||
`whereJsonDoesntContain` methods:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereJsonContains('options->languages', ['en', 'de'])
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereJsonDoesntContain('options->languages', ['en', 'de'])
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonContains('options->languages', ['en', 'de'])
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonDoesntContain('options->languages', ['en', 'de'])
|
||
->get();
|
||
|
||
In addition, you may use the `whereJsonContainsKey` or
|
||
`whereJsonDoesntContainKey` methods to retrieve the results that include or do
|
||
not include a JSON key:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereJsonContainsKey('preferences->dietary_requirements')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereJsonDoesntContainKey('preferences->dietary_requirements')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonContainsKey('preferences->dietary_requirements')
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonDoesntContainKey('preferences->dietary_requirements')
|
||
->get();
|
||
|
||
Finally, you may use `whereJsonLength` method to query JSON arrays by their
|
||
length:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereJsonLength('options->languages', 0)
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereJsonLength('options->languages', '>', 1)
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonLength('options->languages', 0)
|
||
->get();
|
||
|
||
$users = DB::table('users')
|
||
->whereJsonLength('options->languages', '>', 1)
|
||
->get();
|
||
|
||
### Additional Where Clauses
|
||
|
||
**whereLike / orWhereLike / whereNotLike / orWhereNotLike**
|
||
|
||
The `whereLike` method allows you to add "LIKE" clauses to your query for
|
||
pattern matching. These methods provide a database-agnostic way of performing
|
||
string matching queries, with the ability to toggle case-sensitivity. By
|
||
default, string matching is case-insensitive:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereLike('name', '%John%')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereLike('name', '%John%')
|
||
->get();
|
||
|
||
You can enable a case-sensitive search via the `caseSensitive` argument:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereLike('name', '%John%', caseSensitive: true)
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereLike('name', '%John%', caseSensitive: true)
|
||
->get();
|
||
|
||
The `orWhereLike` method allows you to add an "or" clause with a LIKE
|
||
condition:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('votes', '>', 100)
|
||
|
||
3 ->orWhereLike('name', '%John%')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->orWhereLike('name', '%John%')
|
||
->get();
|
||
|
||
The `whereNotLike` method allows you to add "NOT LIKE" clauses to your query:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereNotLike('name', '%John%')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereNotLike('name', '%John%')
|
||
->get();
|
||
|
||
Similarly, you can use `orWhereNotLike` to add an "or" clause with a NOT LIKE
|
||
condition:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('votes', '>', 100)
|
||
|
||
3 ->orWhereNotLike('name', '%John%')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->orWhereNotLike('name', '%John%')
|
||
->get();
|
||
|
||
The `whereLike` case-sensitive search option is currently not supported on SQL
|
||
Server.
|
||
|
||
**whereIn / whereNotIn / orWhereIn / orWhereNotIn**
|
||
|
||
The `whereIn` method verifies that a given column's value is contained within
|
||
the given array:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereIn('id', [1, 2, 3])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereIn('id', [1, 2, 3])
|
||
->get();
|
||
|
||
The `whereNotIn` method verifies that the given column's value is not
|
||
contained in the given array:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereNotIn('id', [1, 2, 3])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereNotIn('id', [1, 2, 3])
|
||
->get();
|
||
|
||
You may also provide a query object as the `whereIn` method's second argument:
|
||
|
||
|
||
|
||
1$activeUsers = DB::table('users')->select('id')->where('is_active', 1);
|
||
|
||
2
|
||
|
||
3$users = DB::table('comments')
|
||
|
||
4 ->whereIn('user_id', $activeUsers)
|
||
|
||
5 ->get();
|
||
|
||
|
||
$activeUsers = DB::table('users')->select('id')->where('is_active', 1);
|
||
|
||
$users = DB::table('comments')
|
||
->whereIn('user_id', $activeUsers)
|
||
->get();
|
||
|
||
The example above will produce the following SQL:
|
||
|
||
|
||
|
||
1select * from comments where user_id in (
|
||
|
||
2 select id
|
||
|
||
3 from users
|
||
|
||
4 where is_active = 1
|
||
|
||
5)
|
||
|
||
|
||
select * from comments where user_id in (
|
||
select id
|
||
from users
|
||
where is_active = 1
|
||
)
|
||
|
||
If you are adding a large array of integer bindings to your query, the
|
||
`whereIntegerInRaw` or `whereIntegerNotInRaw` methods may be used to greatly
|
||
reduce your memory usage.
|
||
|
||
**whereBetween / orWhereBetween**
|
||
|
||
The `whereBetween` method verifies that a column's value is between two
|
||
values:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereBetween('votes', [1, 100])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereBetween('votes', [1, 100])
|
||
->get();
|
||
|
||
**whereNotBetween / orWhereNotBetween**
|
||
|
||
The `whereNotBetween` method verifies that a column's value lies outside of
|
||
two values:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereNotBetween('votes', [1, 100])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereNotBetween('votes', [1, 100])
|
||
->get();
|
||
|
||
**whereBetweenColumns / whereNotBetweenColumns / orWhereBetweenColumns /
|
||
orWhereNotBetweenColumns**
|
||
|
||
The `whereBetweenColumns` method verifies that a column's value is between the
|
||
two values of two columns in the same table row:
|
||
|
||
|
||
|
||
1$patients = DB::table('patients')
|
||
|
||
2 ->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$patients = DB::table('patients')
|
||
->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
|
||
->get();
|
||
|
||
The `whereNotBetweenColumns` method verifies that a column's value lies
|
||
outside the two values of two columns in the same table row:
|
||
|
||
|
||
|
||
1$patients = DB::table('patients')
|
||
|
||
2 ->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$patients = DB::table('patients')
|
||
->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight'])
|
||
->get();
|
||
|
||
**whereValueBetween / whereValueNotBetween / orWhereValueBetween /
|
||
orWhereValueNotBetween**
|
||
|
||
The `whereValueBetween` method verifies that a given value is between the
|
||
values of two columns of the same type in the same table row:
|
||
|
||
|
||
|
||
1$patients = DB::table('products')
|
||
|
||
2 ->whereValueBetween(100, ['min_price', 'max_price'])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$patients = DB::table('products')
|
||
->whereValueBetween(100, ['min_price', 'max_price'])
|
||
->get();
|
||
|
||
The `whereValueNotBetween` method verifies that a value lies outside the
|
||
values of two columns in the same table row:
|
||
|
||
|
||
|
||
1$patients = DB::table('products')
|
||
|
||
2 ->whereValueNotBetween(100, ['min_price', 'max_price'])
|
||
|
||
3 ->get();
|
||
|
||
|
||
$patients = DB::table('products')
|
||
->whereValueNotBetween(100, ['min_price', 'max_price'])
|
||
->get();
|
||
|
||
**whereNull / whereNotNull / orWhereNull / orWhereNotNull**
|
||
|
||
The `whereNull` method verifies that the value of the given column is `NULL`:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereNull('updated_at')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereNull('updated_at')
|
||
->get();
|
||
|
||
The `whereNotNull` method verifies that the column's value is not `NULL`:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereNotNull('updated_at')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereNotNull('updated_at')
|
||
->get();
|
||
|
||
**whereDate / whereMonth / whereDay / whereYear / whereTime**
|
||
|
||
The `whereDate` method may be used to compare a column's value against a date:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereDate('created_at', '2016-12-31')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereDate('created_at', '2016-12-31')
|
||
->get();
|
||
|
||
The `whereMonth` method may be used to compare a column's value against a
|
||
specific month:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereMonth('created_at', '12')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereMonth('created_at', '12')
|
||
->get();
|
||
|
||
The `whereDay` method may be used to compare a column's value against a
|
||
specific day of the month:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereDay('created_at', '31')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereDay('created_at', '31')
|
||
->get();
|
||
|
||
The `whereYear` method may be used to compare a column's value against a
|
||
specific year:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereYear('created_at', '2016')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereYear('created_at', '2016')
|
||
->get();
|
||
|
||
The `whereTime` method may be used to compare a column's value against a
|
||
specific time:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereTime('created_at', '=', '11:20:45')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereTime('created_at', '=', '11:20:45')
|
||
->get();
|
||
|
||
**wherePast / whereFuture / whereToday / whereBeforeToday / whereAfterToday**
|
||
|
||
The `wherePast` and `whereFuture` methods may be used to determine if a
|
||
column's value is in the past or future:
|
||
|
||
|
||
|
||
1$invoices = DB::table('invoices')
|
||
|
||
2 ->wherePast('due_at')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$invoices = DB::table('invoices')
|
||
|
||
6 ->whereFuture('due_at')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$invoices = DB::table('invoices')
|
||
->wherePast('due_at')
|
||
->get();
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereFuture('due_at')
|
||
->get();
|
||
|
||
The `whereNowOrPast` and `whereNowOrFuture` methods may be used to determine
|
||
if a column's value is in the past or future, inclusive of the current date
|
||
and time:
|
||
|
||
|
||
|
||
1$invoices = DB::table('invoices')
|
||
|
||
2 ->whereNowOrPast('due_at')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$invoices = DB::table('invoices')
|
||
|
||
6 ->whereNowOrFuture('due_at')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereNowOrPast('due_at')
|
||
->get();
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereNowOrFuture('due_at')
|
||
->get();
|
||
|
||
The `whereToday`, `whereBeforeToday`, and `whereAfterToday` methods may be
|
||
used to determine if a column's value is today, before today, or after today,
|
||
respectively:
|
||
|
||
|
||
|
||
1$invoices = DB::table('invoices')
|
||
|
||
2 ->whereToday('due_at')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$invoices = DB::table('invoices')
|
||
|
||
6 ->whereBeforeToday('due_at')
|
||
|
||
7 ->get();
|
||
|
||
8
|
||
|
||
9$invoices = DB::table('invoices')
|
||
|
||
10 ->whereAfterToday('due_at')
|
||
|
||
11 ->get();
|
||
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereToday('due_at')
|
||
->get();
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereBeforeToday('due_at')
|
||
->get();
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereAfterToday('due_at')
|
||
->get();
|
||
|
||
Similarly, the `whereTodayOrBefore` and `whereTodayOrAfter` methods may be
|
||
used to determine if a column's value is before today or after today,
|
||
inclusive of today's date:
|
||
|
||
|
||
|
||
1$invoices = DB::table('invoices')
|
||
|
||
2 ->whereTodayOrBefore('due_at')
|
||
|
||
3 ->get();
|
||
|
||
4
|
||
|
||
5$invoices = DB::table('invoices')
|
||
|
||
6 ->whereTodayOrAfter('due_at')
|
||
|
||
7 ->get();
|
||
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereTodayOrBefore('due_at')
|
||
->get();
|
||
|
||
$invoices = DB::table('invoices')
|
||
->whereTodayOrAfter('due_at')
|
||
->get();
|
||
|
||
**whereColumn / orWhereColumn**
|
||
|
||
The `whereColumn` method may be used to verify that two columns are equal:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereColumn('first_name', 'last_name')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereColumn('first_name', 'last_name')
|
||
->get();
|
||
|
||
You may also pass a comparison operator to the `whereColumn` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereColumn('updated_at', '>', 'created_at')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereColumn('updated_at', '>', 'created_at')
|
||
->get();
|
||
|
||
You may also pass an array of column comparisons to the `whereColumn` method.
|
||
These conditions will be joined using the `and` operator:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereColumn([
|
||
|
||
3 ['first_name', '=', 'last_name'],
|
||
|
||
4 ['updated_at', '>', 'created_at'],
|
||
|
||
5 ])->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereColumn([
|
||
['first_name', '=', 'last_name'],
|
||
['updated_at', '>', 'created_at'],
|
||
])->get();
|
||
|
||
### Logical Grouping
|
||
|
||
Sometimes you may need to group several "where" clauses within parentheses in
|
||
order to achieve your query's desired logical grouping. In fact, you should
|
||
generally always group calls to the `orWhere` method in parentheses in order
|
||
to avoid unexpected query behavior. To accomplish this, you may pass a closure
|
||
to the `where` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->where('name', '=', 'John')
|
||
|
||
3 ->where(function (Builder $query) {
|
||
|
||
4 $query->where('votes', '>', 100)
|
||
|
||
5 ->orWhere('title', '=', 'Admin');
|
||
|
||
6 })
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->where('name', '=', 'John')
|
||
->where(function (Builder $query) {
|
||
$query->where('votes', '>', 100)
|
||
->orWhere('title', '=', 'Admin');
|
||
})
|
||
->get();
|
||
|
||
As you can see, passing a closure into the `where` method instructs the query
|
||
builder to begin a constraint group. The closure will receive a query builder
|
||
instance which you can use to set the constraints that should be contained
|
||
within the parenthesis group. The example above will produce the following
|
||
SQL:
|
||
|
||
|
||
|
||
1select * from users where name = 'John' and (votes > 100 or title = 'Admin')
|
||
|
||
|
||
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
|
||
|
||
You should always group `orWhere` calls in order to avoid unexpected behavior
|
||
when global scopes are applied.
|
||
|
||
## Advanced Where Clauses
|
||
|
||
### Where Exists Clauses
|
||
|
||
The `whereExists` method allows you to write "where exists" SQL clauses. The
|
||
`whereExists` method accepts a closure which will receive a query builder
|
||
instance, allowing you to define the query that should be placed inside of the
|
||
"exists" clause:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereExists(function (Builder $query) {
|
||
|
||
3 $query->select(DB::raw(1))
|
||
|
||
4 ->from('orders')
|
||
|
||
5 ->whereColumn('orders.user_id', 'users.id');
|
||
|
||
6 })
|
||
|
||
7 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereExists(function (Builder $query) {
|
||
$query->select(DB::raw(1))
|
||
->from('orders')
|
||
->whereColumn('orders.user_id', 'users.id');
|
||
})
|
||
->get();
|
||
|
||
Alternatively, you may provide a query object to the `whereExists` method
|
||
instead of a closure:
|
||
|
||
|
||
|
||
1$orders = DB::table('orders')
|
||
|
||
2 ->select(DB::raw(1))
|
||
|
||
3 ->whereColumn('orders.user_id', 'users.id');
|
||
|
||
4
|
||
|
||
5$users = DB::table('users')
|
||
|
||
6 ->whereExists($orders)
|
||
|
||
7 ->get();
|
||
|
||
|
||
$orders = DB::table('orders')
|
||
->select(DB::raw(1))
|
||
->whereColumn('orders.user_id', 'users.id');
|
||
|
||
$users = DB::table('users')
|
||
->whereExists($orders)
|
||
->get();
|
||
|
||
Both of the examples above will produce the following SQL:
|
||
|
||
|
||
|
||
1select * from users
|
||
|
||
2where exists (
|
||
|
||
3 select 1
|
||
|
||
4 from orders
|
||
|
||
5 where orders.user_id = users.id
|
||
|
||
6)
|
||
|
||
|
||
select * from users
|
||
where exists (
|
||
select 1
|
||
from orders
|
||
where orders.user_id = users.id
|
||
)
|
||
|
||
### Subquery Where Clauses
|
||
|
||
Sometimes you may need to construct a "where" clause that compares the results
|
||
of a subquery to a given value. You may accomplish this by passing a closure
|
||
and a value to the `where` method. For example, the following query will
|
||
retrieve all users who have a recent "membership" of a given type;
|
||
|
||
|
||
|
||
1use App\Models\User;
|
||
|
||
2use Illuminate\Database\Query\Builder;
|
||
|
||
3
|
||
|
||
4$users = User::where(function (Builder $query) {
|
||
|
||
5 $query->select('type')
|
||
|
||
6 ->from('membership')
|
||
|
||
7 ->whereColumn('membership.user_id', 'users.id')
|
||
|
||
8 ->orderByDesc('membership.start_date')
|
||
|
||
9 ->limit(1);
|
||
|
||
10}, 'Pro')->get();
|
||
|
||
|
||
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();
|
||
|
||
Or, you may need to construct a "where" clause that compares a column to the
|
||
results of a subquery. You may accomplish this by passing a column, operator,
|
||
and closure to the `where` method. For example, the following query will
|
||
retrieve all income records where the amount is less than average;
|
||
|
||
|
||
|
||
1use App\Models\Income;
|
||
|
||
2use Illuminate\Database\Query\Builder;
|
||
|
||
3
|
||
|
||
4$incomes = Income::where('amount', '<', function (Builder $query) {
|
||
|
||
5 $query->selectRaw('avg(i.amount)')->from('incomes as i');
|
||
|
||
6})->get();
|
||
|
||
|
||
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();
|
||
|
||
### Full Text Where Clauses
|
||
|
||
Full text where clauses are currently supported by MariaDB, MySQL, and
|
||
PostgreSQL.
|
||
|
||
The `whereFullText` and `orWhereFullText` methods may be used to add full text
|
||
"where" clauses to a query for columns that have [full text
|
||
indexes](/docs/12.x/migrations#available-index-types). These methods will be
|
||
transformed into the appropriate SQL for the underlying database system by
|
||
Laravel. For example, a `MATCH AGAINST` clause will be generated for
|
||
applications utilizing MariaDB or MySQL:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->whereFullText('bio', 'web developer')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->whereFullText('bio', 'web developer')
|
||
->get();
|
||
|
||
## Ordering, Grouping, Limit and Offset
|
||
|
||
### Ordering
|
||
|
||
#### The `orderBy` Method
|
||
|
||
The `orderBy` method allows you to sort the results of the query by a given
|
||
column. The first argument accepted by the `orderBy` method should be the
|
||
column you wish to sort by, while the second argument determines the direction
|
||
of the sort and may be either `asc` or `desc`:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->orderBy('name', 'desc')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->orderBy('name', 'desc')
|
||
->get();
|
||
|
||
To sort by multiple columns, you may simply invoke `orderBy` as many times as
|
||
necessary:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->orderBy('name', 'desc')
|
||
|
||
3 ->orderBy('email', 'asc')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->orderBy('name', 'desc')
|
||
->orderBy('email', 'asc')
|
||
->get();
|
||
|
||
The sort direction is optional, and is ascending by default. If you want to
|
||
sort in descending order, you can specify the second parameter for the
|
||
`orderBy` method, or just use `orderByDesc`:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->orderByDesc('verified_at')
|
||
|
||
3 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->orderByDesc('verified_at')
|
||
->get();
|
||
|
||
Finally, using the `->` operator, the results can be sorted by a value within
|
||
a JSON column:
|
||
|
||
|
||
|
||
1$corporations = DB::table('corporations')
|
||
|
||
2 ->where('country', 'US')
|
||
|
||
3 ->orderBy('location->state')
|
||
|
||
4 ->get();
|
||
|
||
|
||
$corporations = DB::table('corporations')
|
||
->where('country', 'US')
|
||
->orderBy('location->state')
|
||
->get();
|
||
|
||
#### The `latest` and `oldest` Methods
|
||
|
||
The `latest` and `oldest` methods allow you to easily order results by date.
|
||
By default, the result will be ordered by the table's `created_at` column. Or,
|
||
you may pass the column name that you wish to sort by:
|
||
|
||
|
||
|
||
1$user = DB::table('users')
|
||
|
||
2 ->latest()
|
||
|
||
3 ->first();
|
||
|
||
|
||
$user = DB::table('users')
|
||
->latest()
|
||
->first();
|
||
|
||
#### Random Ordering
|
||
|
||
The `inRandomOrder` method may be used to sort the query results randomly. For
|
||
example, you may use this method to fetch a random user:
|
||
|
||
|
||
|
||
1$randomUser = DB::table('users')
|
||
|
||
2 ->inRandomOrder()
|
||
|
||
3 ->first();
|
||
|
||
|
||
$randomUser = DB::table('users')
|
||
->inRandomOrder()
|
||
->first();
|
||
|
||
#### Removing Existing Orderings
|
||
|
||
The `reorder` method removes all of the "order by" clauses that have
|
||
previously been applied to the query:
|
||
|
||
|
||
|
||
1$query = DB::table('users')->orderBy('name');
|
||
|
||
2
|
||
|
||
3$unorderedUsers = $query->reorder()->get();
|
||
|
||
|
||
$query = DB::table('users')->orderBy('name');
|
||
|
||
$unorderedUsers = $query->reorder()->get();
|
||
|
||
You may pass a column and direction when calling the `reorder` method in order
|
||
to remove all existing "order by" clauses and apply an entirely new order to
|
||
the query:
|
||
|
||
|
||
|
||
1$query = DB::table('users')->orderBy('name');
|
||
|
||
2
|
||
|
||
3$usersOrderedByEmail = $query->reorder('email', 'desc')->get();
|
||
|
||
|
||
$query = DB::table('users')->orderBy('name');
|
||
|
||
$usersOrderedByEmail = $query->reorder('email', 'desc')->get();
|
||
|
||
For convenience, you may use the `reorderDesc` method to reorder the query
|
||
results in descending order:
|
||
|
||
|
||
|
||
1$query = DB::table('users')->orderBy('name');
|
||
|
||
2
|
||
|
||
3$usersOrderedByEmail = $query->reorderDesc('email')->get();
|
||
|
||
|
||
$query = DB::table('users')->orderBy('name');
|
||
|
||
$usersOrderedByEmail = $query->reorderDesc('email')->get();
|
||
|
||
### Grouping
|
||
|
||
#### The `groupBy` and `having` Methods
|
||
|
||
As you might expect, the `groupBy` and `having` methods may be used to group
|
||
the query results. The `having` method's signature is similar to that of the
|
||
`where` method:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->groupBy('account_id')
|
||
|
||
3 ->having('account_id', '>', 100)
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->groupBy('account_id')
|
||
->having('account_id', '>', 100)
|
||
->get();
|
||
|
||
You can use the `havingBetween` method to filter the results within a given
|
||
range:
|
||
|
||
|
||
|
||
1$report = DB::table('orders')
|
||
|
||
2 ->selectRaw('count(id) as number_of_orders, customer_id')
|
||
|
||
3 ->groupBy('customer_id')
|
||
|
||
4 ->havingBetween('number_of_orders', [5, 15])
|
||
|
||
5 ->get();
|
||
|
||
|
||
$report = DB::table('orders')
|
||
->selectRaw('count(id) as number_of_orders, customer_id')
|
||
->groupBy('customer_id')
|
||
->havingBetween('number_of_orders', [5, 15])
|
||
->get();
|
||
|
||
You may pass multiple arguments to the `groupBy` method to group by multiple
|
||
columns:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->groupBy('first_name', 'status')
|
||
|
||
3 ->having('account_id', '>', 100)
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->groupBy('first_name', 'status')
|
||
->having('account_id', '>', 100)
|
||
->get();
|
||
|
||
To build more advanced `having` statements, see the havingRaw method.
|
||
|
||
### Limit and Offset
|
||
|
||
You may use the `limit` and `offset` methods to limit the number of results
|
||
returned from the query or to skip a given number of results in the query:
|
||
|
||
|
||
|
||
1$users = DB::table('users')
|
||
|
||
2 ->offset(10)
|
||
|
||
3 ->limit(5)
|
||
|
||
4 ->get();
|
||
|
||
|
||
$users = DB::table('users')
|
||
->offset(10)
|
||
->limit(5)
|
||
->get();
|
||
|
||
## Conditional Clauses
|
||
|
||
Sometimes you may want certain query clauses to apply to a query based on
|
||
another condition. For instance, you may only want to apply a `where`
|
||
statement if a given input value is present on the incoming HTTP request. You
|
||
may accomplish this using the `when` method:
|
||
|
||
|
||
|
||
1$role = $request->input('role');
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')
|
||
|
||
4 ->when($role, function (Builder $query, string $role) {
|
||
|
||
5 $query->where('role_id', $role);
|
||
|
||
6 })
|
||
|
||
7 ->get();
|
||
|
||
|
||
$role = $request->input('role');
|
||
|
||
$users = DB::table('users')
|
||
->when($role, function (Builder $query, string $role) {
|
||
$query->where('role_id', $role);
|
||
})
|
||
->get();
|
||
|
||
The `when` method only executes the given closure when the first argument is
|
||
`true`. If the first argument is `false`, the closure will not be executed.
|
||
So, in the example above, the closure given to the `when` method will only be
|
||
invoked if the `role` field is present on the incoming request and evaluates
|
||
to `true`.
|
||
|
||
You may pass another closure as the third argument to the `when` method. This
|
||
closure will only execute if the first argument evaluates as `false`. To
|
||
illustrate how this feature may be used, we will use it to configure the
|
||
default ordering of a query:
|
||
|
||
|
||
|
||
1$sortByVotes = $request->boolean('sort_by_votes');
|
||
|
||
2
|
||
|
||
3$users = DB::table('users')
|
||
|
||
4 ->when($sortByVotes, function (Builder $query, bool $sortByVotes) {
|
||
|
||
5 $query->orderBy('votes');
|
||
|
||
6 }, function (Builder $query) {
|
||
|
||
7 $query->orderBy('name');
|
||
|
||
8 })
|
||
|
||
9 ->get();
|
||
|
||
|
||
$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 Statements
|
||
|
||
The query builder also provides an `insert` method that may be used to insert
|
||
records into the database table. The `insert` method accepts an array of
|
||
column names and values:
|
||
|
||
|
||
|
||
1DB::table('users')->insert([
|
||
|
||
2 'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||
|
||
3 'votes' => 0
|
||
|
||
4]);
|
||
|
||
|
||
DB::table('users')->insert([
|
||
'email' => '[[email protected]](/cdn-cgi/l/email-protection)',
|
||
'votes' => 0
|
||
]);
|
||
|
||
You may insert several records at once by passing an array of arrays. Each
|
||
array represents a record that should be inserted into the table:
|
||
|
||
|
||
|
||
1DB::table('users')->insert([
|
||
|
||
2 ['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0],
|
||
|
||
3 ['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0],
|
||
|
||
4]);
|
||
|
||
|
||
DB::table('users')->insert([
|
||
['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0],
|
||
['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0],
|
||
]);
|
||
|
||
The `insertOrIgnore` method will ignore errors while inserting records into
|
||
the database. When using this method, you should be aware that duplicate
|
||
record errors will be ignored and other types of errors may also be ignored
|
||
depending on the database engine. For example, `insertOrIgnore` will [bypass
|
||
MySQL's strict mode](https://dev.mysql.com/doc/refman/en/sql-mode.html#ignore-
|
||
effect-on-execution):
|
||
|
||
|
||
|
||
1DB::table('users')->insertOrIgnore([
|
||
|
||
2 ['id' => 1, 'email' => '[[email protected]](/cdn-cgi/l/email-protection)'],
|
||
|
||
3 ['id' => 2, 'email' => '[[email protected]](/cdn-cgi/l/email-protection)'],
|
||
|
||
4]);
|
||
|
||
|
||
DB::table('users')->insertOrIgnore([
|
||
['id' => 1, 'email' => '[[email protected]](/cdn-cgi/l/email-protection)'],
|
||
['id' => 2, 'email' => '[[email protected]](/cdn-cgi/l/email-protection)'],
|
||
]);
|
||
|
||
The `insertUsing` method will insert new records into the table while using a
|
||
subquery to determine the data that should be inserted:
|
||
|
||
|
||
|
||
1DB::table('pruned_users')->insertUsing([
|
||
|
||
2 'id', 'name', 'email', 'email_verified_at'
|
||
|
||
3], DB::table('users')->select(
|
||
|
||
4 'id', 'name', 'email', 'email_verified_at'
|
||
|
||
5)->where('updated_at', '<=', now()->subMonth()));
|
||
|
||
|
||
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()));
|
||
|
||
#### Auto-Incrementing IDs
|
||
|
||
If the table has an auto-incrementing id, use the `insertGetId` method to
|
||
insert a record and then retrieve the ID:
|
||
|
||
|
||
|
||
1$id = DB::table('users')->insertGetId(
|
||
|
||
2 ['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0]
|
||
|
||
3);
|
||
|
||
|
||
$id = DB::table('users')->insertGetId(
|
||
['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'votes' => 0]
|
||
);
|
||
|
||
When using PostgreSQL the `insertGetId` method expects the auto-incrementing
|
||
column to be named `id`. If you would like to retrieve the ID from a different
|
||
"sequence", you may pass the column name as the second parameter to the
|
||
`insertGetId` method.
|
||
|
||
### Upserts
|
||
|
||
The `upsert` method will insert records that do not exist and update the
|
||
records that already exist with new values that you may specify. The method's
|
||
first argument consists of the values to insert or update, while the second
|
||
argument lists the column(s) that uniquely identify records within the
|
||
associated table. The method's third and final argument is an array of columns
|
||
that should be updated if a matching record already exists in the database:
|
||
|
||
|
||
|
||
1DB::table('flights')->upsert(
|
||
|
||
2 [
|
||
|
||
3 ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
|
||
|
||
4 ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
|
||
|
||
5 ],
|
||
|
||
6 ['departure', 'destination'],
|
||
|
||
7 ['price']
|
||
|
||
8);
|
||
|
||
|
||
DB::table('flights')->upsert(
|
||
[
|
||
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
|
||
['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
|
||
],
|
||
['departure', 'destination'],
|
||
['price']
|
||
);
|
||
|
||
In the example above, Laravel will attempt to insert two records. If a record
|
||
already exists with the same `departure` and `destination` column values,
|
||
Laravel will update that record's `price` column.
|
||
|
||
All databases except SQL Server require the columns in the second argument of
|
||
the `upsert` method to have a "primary" or "unique" index. In addition, the
|
||
MariaDB and MySQL database drivers ignore the second argument of the `upsert`
|
||
method and always use the "primary" and "unique" indexes of the table to
|
||
detect existing records.
|
||
|
||
## Update Statements
|
||
|
||
In addition to inserting records into the database, the query builder can also
|
||
update existing records using the `update` method. The `update` method, like
|
||
the `insert` method, accepts an array of column and value pairs indicating the
|
||
columns to be updated. The `update` method returns the number of affected
|
||
rows. You may constrain the `update` query using `where` clauses:
|
||
|
||
|
||
|
||
1$affected = DB::table('users')
|
||
|
||
2 ->where('id', 1)
|
||
|
||
3 ->update(['votes' => 1]);
|
||
|
||
|
||
$affected = DB::table('users')
|
||
->where('id', 1)
|
||
->update(['votes' => 1]);
|
||
|
||
#### Update or Insert
|
||
|
||
Sometimes you may want to update an existing record in the database or create
|
||
it if no matching record exists. In this scenario, the `updateOrInsert` method
|
||
may be used. The `updateOrInsert` method accepts two arguments: an array of
|
||
conditions by which to find the record, and an array of column and value pairs
|
||
indicating the columns to be updated.
|
||
|
||
The `updateOrInsert` method will attempt to locate a matching database record
|
||
using the first argument's column and value pairs. If the record exists, it
|
||
will be updated with the values in the second argument. If the record cannot
|
||
be found, a new record will be inserted with the merged attributes of both
|
||
arguments:
|
||
|
||
|
||
|
||
1DB::table('users')
|
||
|
||
2 ->updateOrInsert(
|
||
|
||
3 ['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'name' => 'John'],
|
||
|
||
4 ['votes' => '2']
|
||
|
||
5 );
|
||
|
||
|
||
DB::table('users')
|
||
->updateOrInsert(
|
||
['email' => '[[email protected]](/cdn-cgi/l/email-protection)', 'name' => 'John'],
|
||
['votes' => '2']
|
||
);
|
||
|
||
You may provide a closure to the `updateOrInsert` method to customize the
|
||
attributes that are updated or inserted into the database based on the
|
||
existence of a matching record:
|
||
|
||
|
||
|
||
1DB::table('users')->updateOrInsert(
|
||
|
||
2 ['user_id' => $user_id],
|
||
|
||
3 fn ($exists) => $exists ? [
|
||
|
||
4 'name' => $data['name'],
|
||
|
||
5 'email' => $data['email'],
|
||
|
||
6 ] : [
|
||
|
||
7 'name' => $data['name'],
|
||
|
||
8 'email' => $data['email'],
|
||
|
||
9 'marketable' => true,
|
||
|
||
10 ],
|
||
|
||
11);
|
||
|
||
|
||
DB::table('users')->updateOrInsert(
|
||
['user_id' => $user_id],
|
||
fn ($exists) => $exists ? [
|
||
'name' => $data['name'],
|
||
'email' => $data['email'],
|
||
] : [
|
||
'name' => $data['name'],
|
||
'email' => $data['email'],
|
||
'marketable' => true,
|
||
],
|
||
);
|
||
|
||
### Updating JSON Columns
|
||
|
||
When updating a JSON column, you should use `->` syntax to update the
|
||
appropriate key in the JSON object. This operation is supported on MariaDB
|
||
10.3+, MySQL 5.7+, and PostgreSQL 9.5+:
|
||
|
||
|
||
|
||
1$affected = DB::table('users')
|
||
|
||
2 ->where('id', 1)
|
||
|
||
3 ->update(['options->enabled' => true]);
|
||
|
||
|
||
$affected = DB::table('users')
|
||
->where('id', 1)
|
||
->update(['options->enabled' => true]);
|
||
|
||
### Increment and Decrement
|
||
|
||
The query builder also provides convenient methods for incrementing or
|
||
decrementing the value of a given column. Both of these methods accept at
|
||
least one argument: the column to modify. A second argument may be provided to
|
||
specify the amount by which the column should be incremented or decremented:
|
||
|
||
|
||
|
||
1DB::table('users')->increment('votes');
|
||
|
||
2
|
||
|
||
3DB::table('users')->increment('votes', 5);
|
||
|
||
4
|
||
|
||
5DB::table('users')->decrement('votes');
|
||
|
||
6
|
||
|
||
7DB::table('users')->decrement('votes', 5);
|
||
|
||
|
||
DB::table('users')->increment('votes');
|
||
|
||
DB::table('users')->increment('votes', 5);
|
||
|
||
DB::table('users')->decrement('votes');
|
||
|
||
DB::table('users')->decrement('votes', 5);
|
||
|
||
If needed, you may also specify additional columns to update during the
|
||
increment or decrement operation:
|
||
|
||
|
||
|
||
1DB::table('users')->increment('votes', 1, ['name' => 'John']);
|
||
|
||
|
||
DB::table('users')->increment('votes', 1, ['name' => 'John']);
|
||
|
||
In addition, you may increment or decrement multiple columns at once using the
|
||
`incrementEach` and `decrementEach` methods:
|
||
|
||
|
||
|
||
1DB::table('users')->incrementEach([
|
||
|
||
2 'votes' => 5,
|
||
|
||
3 'balance' => 100,
|
||
|
||
4]);
|
||
|
||
|
||
DB::table('users')->incrementEach([
|
||
'votes' => 5,
|
||
'balance' => 100,
|
||
]);
|
||
|
||
## Delete Statements
|
||
|
||
The query builder's `delete` method may be used to delete records from the
|
||
table. The `delete` method returns the number of affected rows. You may
|
||
constrain `delete` statements by adding "where" clauses before calling the
|
||
`delete` method:
|
||
|
||
|
||
|
||
1$deleted = DB::table('users')->delete();
|
||
|
||
2
|
||
|
||
3$deleted = DB::table('users')->where('votes', '>', 100)->delete();
|
||
|
||
|
||
$deleted = DB::table('users')->delete();
|
||
|
||
$deleted = DB::table('users')->where('votes', '>', 100)->delete();
|
||
|
||
## Pessimistic Locking
|
||
|
||
The query builder also includes a few functions to help you achieve
|
||
"pessimistic locking" when executing your `select` statements. To execute a
|
||
statement with a "shared lock", you may call the `sharedLock` method. A shared
|
||
lock prevents the selected rows from being modified until your transaction is
|
||
committed:
|
||
|
||
|
||
|
||
1DB::table('users')
|
||
|
||
2 ->where('votes', '>', 100)
|
||
|
||
3 ->sharedLock()
|
||
|
||
4 ->get();
|
||
|
||
|
||
DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->sharedLock()
|
||
->get();
|
||
|
||
Alternatively, you may use the `lockForUpdate` method. A "for update" lock
|
||
prevents the selected records from being modified or from being selected with
|
||
another shared lock:
|
||
|
||
|
||
|
||
1DB::table('users')
|
||
|
||
2 ->where('votes', '>', 100)
|
||
|
||
3 ->lockForUpdate()
|
||
|
||
4 ->get();
|
||
|
||
|
||
DB::table('users')
|
||
->where('votes', '>', 100)
|
||
->lockForUpdate()
|
||
->get();
|
||
|
||
While not obligatory, it is recommended to wrap pessimistic locks within a
|
||
[transaction](/docs/12.x/database#database-transactions). This ensures that
|
||
the data retrieved remains unaltered in the database until the entire
|
||
operation completes. In case of a failure, the transaction will roll back any
|
||
changes and release the locks automatically:
|
||
|
||
|
||
|
||
1DB::transaction(function () {
|
||
|
||
2 $sender = DB::table('users')
|
||
|
||
3 ->lockForUpdate()
|
||
|
||
4 ->find(1);
|
||
|
||
5
|
||
|
||
6 $receiver = DB::table('users')
|
||
|
||
7 ->lockForUpdate()
|
||
|
||
8 ->find(2);
|
||
|
||
9
|
||
|
||
10 if ($sender->balance < 100) {
|
||
|
||
11 throw new RuntimeException('Balance too low.');
|
||
|
||
12 }
|
||
|
||
13
|
||
|
||
14 DB::table('users')
|
||
|
||
15 ->where('id', $sender->id)
|
||
|
||
16 ->update([
|
||
|
||
17 'balance' => $sender->balance - 100
|
||
|
||
18 ]);
|
||
|
||
19
|
||
|
||
20 DB::table('users')
|
||
|
||
21 ->where('id', $receiver->id)
|
||
|
||
22 ->update([
|
||
|
||
23 'balance' => $receiver->balance + 100
|
||
|
||
24 ]);
|
||
|
||
25});
|
||
|
||
|
||
DB::transaction(function () {
|
||
$sender = DB::table('users')
|
||
->lockForUpdate()
|
||
->find(1);
|
||
|
||
$receiver = DB::table('users')
|
||
->lockForUpdate()
|
||
->find(2);
|
||
|
||
if ($sender->balance < 100) {
|
||
throw new RuntimeException('Balance too low.');
|
||
}
|
||
|
||
DB::table('users')
|
||
->where('id', $sender->id)
|
||
->update([
|
||
'balance' => $sender->balance - 100
|
||
]);
|
||
|
||
DB::table('users')
|
||
->where('id', $receiver->id)
|
||
->update([
|
||
'balance' => $receiver->balance + 100
|
||
]);
|
||
});
|
||
|
||
## Reusable Query Components
|
||
|
||
If you have repeated query logic throughout your application, you may extract
|
||
the logic into reusable objects using the query builder's `tap` and `pipe`
|
||
methods. Imagine you have these two different queries in your application:
|
||
|
||
|
||
|
||
1use Illuminate\Database\Query\Builder;
|
||
|
||
2use Illuminate\Support\Facades\DB;
|
||
|
||
3
|
||
|
||
4$destination = $request->query('destination');
|
||
|
||
5
|
||
|
||
6DB::table('flights')
|
||
|
||
7 ->when($destination, function (Builder $query, string $destination) {
|
||
|
||
8 $query->where('destination', $destination);
|
||
|
||
9 })
|
||
|
||
10 ->orderByDesc('price')
|
||
|
||
11 ->get();
|
||
|
||
12
|
||
|
||
13// ...
|
||
|
||
14
|
||
|
||
15$destination = $request->query('destination');
|
||
|
||
16
|
||
|
||
17DB::table('flights')
|
||
|
||
18 ->when($destination, function (Builder $query, string $destination) {
|
||
|
||
19 $query->where('destination', $destination);
|
||
|
||
20 })
|
||
|
||
21 ->where('user', $request->user()->id)
|
||
|
||
22 ->orderBy('destination')
|
||
|
||
23 ->get();
|
||
|
||
|
||
use Illuminate\Database\Query\Builder;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
$destination = $request->query('destination');
|
||
|
||
DB::table('flights')
|
||
->when($destination, function (Builder $query, string $destination) {
|
||
$query->where('destination', $destination);
|
||
})
|
||
->orderByDesc('price')
|
||
->get();
|
||
|
||
// ...
|
||
|
||
$destination = $request->query('destination');
|
||
|
||
DB::table('flights')
|
||
->when($destination, function (Builder $query, string $destination) {
|
||
$query->where('destination', $destination);
|
||
})
|
||
->where('user', $request->user()->id)
|
||
->orderBy('destination')
|
||
->get();
|
||
|
||
You may like to extract the destination filtering that is common between the
|
||
queries into a reusable object:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Scopes;
|
||
|
||
4
|
||
|
||
5use Illuminate\Database\Query\Builder;
|
||
|
||
6
|
||
|
||
7class DestinationFilter
|
||
|
||
8{
|
||
|
||
9 public function __construct(
|
||
|
||
10 private ?string $destination,
|
||
|
||
11 ) {
|
||
|
||
12 //
|
||
|
||
13 }
|
||
|
||
14
|
||
|
||
15 public function __invoke(Builder $query): void
|
||
|
||
16 {
|
||
|
||
17 $query->when($this->destination, function (Builder $query) {
|
||
|
||
18 $query->where('destination', $this->destination);
|
||
|
||
19 });
|
||
|
||
20 }
|
||
|
||
21}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Scopes;
|
||
|
||
use Illuminate\Database\Query\Builder;
|
||
|
||
class DestinationFilter
|
||
{
|
||
public function __construct(
|
||
private ?string $destination,
|
||
) {
|
||
//
|
||
}
|
||
|
||
public function __invoke(Builder $query): void
|
||
{
|
||
$query->when($this->destination, function (Builder $query) {
|
||
$query->where('destination', $this->destination);
|
||
});
|
||
}
|
||
}
|
||
|
||
Then, you can use the query builder's `tap` method to apply the object's logic
|
||
to the query:
|
||
|
||
|
||
|
||
1use App\Scopes\DestinationFilter;
|
||
|
||
2use Illuminate\Database\Query\Builder;
|
||
|
||
3use Illuminate\Support\Facades\DB;
|
||
|
||
4
|
||
|
||
5DB::table('flights')
|
||
|
||
6 ->when($destination, function (Builder $query, string $destination) {
|
||
|
||
7 $query->where('destination', $destination);
|
||
|
||
8 })
|
||
|
||
9 ->tap(new DestinationFilter($destination))
|
||
|
||
10 ->orderByDesc('price')
|
||
|
||
11 ->get();
|
||
|
||
12
|
||
|
||
13// ...
|
||
|
||
14
|
||
|
||
15DB::table('flights')
|
||
|
||
16 ->when($destination, function (Builder $query, string $destination) {
|
||
|
||
17 $query->where('destination', $destination);
|
||
|
||
18 })
|
||
|
||
19 ->tap(new DestinationFilter($destination))
|
||
|
||
20 ->where('user', $request->user()->id)
|
||
|
||
21 ->orderBy('destination')
|
||
|
||
22 ->get();
|
||
|
||
|
||
use App\Scopes\DestinationFilter;
|
||
use Illuminate\Database\Query\Builder;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
DB::table('flights')
|
||
->when($destination, function (Builder $query, string $destination) {
|
||
$query->where('destination', $destination);
|
||
})
|
||
->tap(new DestinationFilter($destination))
|
||
->orderByDesc('price')
|
||
->get();
|
||
|
||
// ...
|
||
|
||
DB::table('flights')
|
||
->when($destination, function (Builder $query, string $destination) {
|
||
$query->where('destination', $destination);
|
||
})
|
||
->tap(new DestinationFilter($destination))
|
||
->where('user', $request->user()->id)
|
||
->orderBy('destination')
|
||
->get();
|
||
|
||
#### Query Pipes
|
||
|
||
The `tap` method will always return the query builder. If you would like to
|
||
extract an object that executes the query and returns another value, you may
|
||
use the `pipe` method instead.
|
||
|
||
Consider the following query object that contains shared
|
||
[pagination](/docs/12.x/pagination) logic used throughout an application.
|
||
Unlike the `DestinationFilter`, which applies query conditions to the query,
|
||
the `Paginate` object executes the query and returns a paginator instance:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Scopes;
|
||
|
||
4
|
||
|
||
5use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||
|
||
6use Illuminate\Database\Query\Builder;
|
||
|
||
7
|
||
|
||
8class Paginate
|
||
|
||
9{
|
||
|
||
10 public function __construct(
|
||
|
||
11 private string $sortBy = 'timestamp',
|
||
|
||
12 private string $sortDirection = 'desc',
|
||
|
||
13 private int $perPage = 25,
|
||
|
||
14 ) {
|
||
|
||
15 //
|
||
|
||
16 }
|
||
|
||
17
|
||
|
||
18 public function __invoke(Builder $query): LengthAwarePaginator
|
||
|
||
19 {
|
||
|
||
20 return $query->orderBy($this->sortBy, $this->sortDirection)
|
||
|
||
21 ->paginate($this->perPage, pageName: 'p');
|
||
|
||
22 }
|
||
|
||
23}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Scopes;
|
||
|
||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||
use Illuminate\Database\Query\Builder;
|
||
|
||
class Paginate
|
||
{
|
||
public function __construct(
|
||
private string $sortBy = 'timestamp',
|
||
private string $sortDirection = 'desc',
|
||
private int $perPage = 25,
|
||
) {
|
||
//
|
||
}
|
||
|
||
public function __invoke(Builder $query): LengthAwarePaginator
|
||
{
|
||
return $query->orderBy($this->sortBy, $this->sortDirection)
|
||
->paginate($this->perPage, pageName: 'p');
|
||
}
|
||
}
|
||
|
||
Using the query builder's `pipe` method, we can leverage this object to apply
|
||
our shared pagination logic:
|
||
|
||
|
||
|
||
1$flights = DB::table('flights')
|
||
|
||
2 ->tap(new DestinationFilter($destination))
|
||
|
||
3 ->pipe(new Paginate);
|
||
|
||
|
||
$flights = DB::table('flights')
|
||
->tap(new DestinationFilter($destination))
|
||
->pipe(new Paginate);
|
||
|
||
## Debugging
|
||
|
||
You may use the `dd` and `dump` methods while building a query to dump the
|
||
current query bindings and SQL. The `dd` method will display the debug
|
||
information and then stop executing the request. The `dump` method will
|
||
display the debug information but allow the request to continue executing:
|
||
|
||
|
||
|
||
1DB::table('users')->where('votes', '>', 100)->dd();
|
||
|
||
2
|
||
|
||
3DB::table('users')->where('votes', '>', 100)->dump();
|
||
|
||
|
||
DB::table('users')->where('votes', '>', 100)->dd();
|
||
|
||
DB::table('users')->where('votes', '>', 100)->dump();
|
||
|
||
The `dumpRawSql` and `ddRawSql` methods may be invoked on a query to dump the
|
||
query's SQL with all parameter bindings properly substituted:
|
||
|
||
|
||
|
||
1DB::table('users')->where('votes', '>', 100)->dumpRawSql();
|
||
|
||
2
|
||
|
||
3DB::table('users')->where('votes', '>', 100)->ddRawSql();
|
||
|
||
|
||
DB::table('users')->where('votes', '>', 100)->dumpRawSql();
|
||
|
||
DB::table('users')->where('votes', '>', 100)->ddRawSql();
|
||
|