hyperf/docs/en/db/querybuilder.md

682 lines
21 KiB
Markdown
Raw Normal View History

2022-10-31 01:47:12 +08:00
# Query builder
2019-03-20 16:21:02 +08:00
2022-10-31 01:47:12 +08:00
## Introduction
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
Hyperf's database query builder provides a convenient interface for creating and running database queries. It can be used to perform most database operations in an application and runs on all supported database systems.
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
Hyperf's query builder uses PDO parameter binding to protect your application from SQL injection attacks. So there is no need to sanitize strings passed as bindings.
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
Only some commonly used tutorials are provided here, and specific tutorials can be viewed on the Laravel official website.
2019-03-18 11:57:25 +08:00
[Laravel Query Builder](https://laravel.com/docs/5.8/queries)
2022-10-31 01:47:12 +08:00
## Get results
2019-03-18 11:57:25 +08:00
2019-03-19 14:52:21 +08:00
```php
2019-03-18 11:57:25 +08:00
use Hyperf\DbConnection\Db;
2019-03-30 23:13:21 +08:00
$users = Db::select('SELECT * FROM user;');
2019-03-18 11:57:25 +08:00
$users = Db::table('user')->get();
2019-03-27 16:39:30 +08:00
$users = Db::table('user')->select('name', 'gender as user_gender')->get();
2019-03-19 14:52:21 +08:00
```
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
The `Db::select()` method returns an array, and the `get` method returns `Hyperf\Utils\Collection`. The element is `stdClass`, so the data of each element can be returned by the following code
2019-03-18 11:57:25 +08:00
2019-03-19 14:52:21 +08:00
```php
2019-03-18 11:57:25 +08:00
<?php
foreach ($users as $user) {
echo $user->name;
}
2019-03-19 14:52:21 +08:00
```
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
### Convert the result to array format
2019-06-14 21:02:46 +08:00
2022-10-31 01:47:12 +08:00
In some scenarios, you may want to use `Array` instead of `stdClass` object structure in the query result, and `Eloquent` removes the default `FetchMode` configured by configuration, then At this point, you can change the configuration by listening to the `Hyperf\Database\Events\StatementPrepared` event through the listener:
2019-06-14 21:02:46 +08:00
```php
<?php
declare(strict_types=1);
namespace App\Listener;
use Hyperf\Database\Events\StatementPrepared;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
use PDO;
/**
* @Listener
*/
class FetchModeListener implements ListenerInterface
{
public function listen(): array
{
return [
StatementPrepared::class,
];
}
public function process(object $event)
{
if ($event instanceof StatementPrepared) {
$event->statement->setFetchMode(PDO::FETCH_ASSOC);
}
}
}
```
2022-10-31 01:47:12 +08:00
### Get the value of a column
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
If you want to get a collection containing a single column of values, you can use the `pluck` method. In the following example, we will get a collection of titles in the roles table:
2019-05-22 14:08:04 +08:00
```php
<?php
use Hyperf\DbConnection\Db;
$names = Db::table('user')->pluck('name');
foreach ($names as $name) {
echo $names;
}
```
2022-10-31 01:47:12 +08:00
You can also specify custom keys for fields in the returned collection:
2019-05-22 14:08:04 +08:00
```php
<?php
use Hyperf\DbConnection\Db;
$roles = Db::table('roles')->pluck('title', 'name');
foreach ($roles as $name => $title) {
echo $title;
}
```
2022-10-31 01:47:12 +08:00
### Chunked results
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
If you need to process thousands of database records, you might consider using the `chunk` method. This method takes a small chunk of the result set at a time and passes it to the `closure` function for processing. This method is very useful when `Command` is writing thousands of pieces of processing data. For example, we can cut the entire user table data into small pieces that process 100 records at a time:
2019-05-22 14:08:04 +08:00
```php
<?php
use Hyperf\DbConnection\Db;
Db::table('user')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
//
}
});
```
2022-10-31 01:47:12 +08:00
You can stop fetching chunked results by returning `false` in the closure:
2019-05-22 14:08:04 +08:00
```php
use Hyperf\DbConnection\Db;
Db::table('user')->orderBy('id')->chunk(100, function ($users) {
return false;
});
```
2022-10-31 01:47:12 +08:00
If you are updating database records while chunking the results, the chunked results may not be the same as expected. Therefore, when updating records in chunks, it is better to use the chunkById method. This method will automatically paginate the results based on the record's primary key:
2019-05-22 14:08:04 +08:00
```php
use Hyperf\DbConnection\Db;
Db::table('user')->where('gender', 1)->chunkById(100, function ($users) {
foreach ($users as $user) {
2019-05-22 14:41:16 +08:00
Db::table('user')
2019-05-22 14:08:04 +08:00
->where('id', $user->id)
->update(['update_time' => time()]);
}
});
```
2022-10-31 01:47:12 +08:00
> Any changes to the primary or foreign keys may affect the block query while updating or deleting records inside the block's callback. This may result in records not being included in the chunked result.
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
### Aggregate query
2019-03-18 12:57:34 +08:00
2022-10-31 01:47:12 +08:00
The framework also provides aggregate class methods such as `count`, `max`, `min`, `avg`, `sum`.
2019-03-18 11:57:25 +08:00
2019-03-19 14:52:21 +08:00
```php
2019-03-18 11:57:25 +08:00
use Hyperf\DbConnection\Db;
$count = Db::table('user')->count();
2019-03-19 14:52:21 +08:00
```
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
#### Determine if the record exists
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
In addition to using the `count` method to determine whether the result of a query condition exists, you can also use the `exists` and `doesntExist` methods:
2019-05-22 14:08:04 +08:00
```php
return Db::table('orders')->where('finalized', 1)->exists();
return Db::table('orders')->where('finalized', 1)->doesntExist();
```
2022-10-31 01:47:12 +08:00
## Inquire
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
### Specify a Select statement
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
Of course you may not always want to get all the columns from the database table. Using the select method, you can customize a select query statement to query the specified fields:
2019-05-22 14:08:04 +08:00
```php
$users = Db::table('user')->select('name', 'email as user_email')->get();
```
2022-10-31 01:47:12 +08:00
The `distinct` method forces the query to return unique results:
2019-05-22 14:08:04 +08:00
```php
$users = Db::table('user')->distinct()->get();
```
2022-10-31 01:47:12 +08:00
If you already have a query builder instance and want to add a field to the existing query, you can use the addSelect method:
2019-05-22 14:08:04 +08:00
```php
$query = Db::table('users')->select('name');
$users = $query->addSelect('age')->get();
```
2022-10-31 01:47:12 +08:00
## Original expression
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
Sometimes you need to use raw expressions in a query, for example to implement `COUNT(0) AS count`, which requires the use of the `raw` method.
2019-03-18 11:57:25 +08:00
2019-03-19 14:52:21 +08:00
```php
2019-03-18 11:57:25 +08:00
use Hyperf\DbConnection\Db;
2019-03-27 16:39:30 +08:00
$res = Db::table('user')->select('gender', Db::raw('COUNT(0) AS `count`'))->groupBy('gender')->get();
2019-03-19 14:52:21 +08:00
```
2019-03-18 11:57:25 +08:00
2022-10-31 01:47:12 +08:00
### Native method
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
The following methods can be used instead of `Db::raw` to insert raw expressions into various parts of the query.
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
The `selectRaw` method can be used in place of `select(Db::raw(...))`. The second parameter of this method is optional, and the value is an array of bound parameters:
2019-05-22 14:08:04 +08:00
```php
$orders = Db::table('order')
->selectRaw('price * ? as price_with_tax', [1.0825])
->get();
```
2022-10-31 01:47:12 +08:00
The `whereRaw` and `orWhereRaw` methods inject native `where` into your query. The second parameter of these two methods is still optional, and the value is still an array of bound parameters:
2019-05-22 14:08:04 +08:00
```php
$orders = Db::table('order')
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
->get();
```
2022-10-31 01:47:12 +08:00
The `havingRaw` and `orHavingRaw` methods can be used to set a raw string as the value of a `having` statement:
2019-05-22 14:08:04 +08:00
```php
$orders = Db::table('order')
->select('department', Db::raw('SUM(price) as total_sales'))
->groupBy('department')
->havingRaw('SUM(price) > ?', [2500])
->get();
```
2022-10-31 01:47:12 +08:00
The `orderByRaw` method can be used to set a raw string as the value of the `order by` clause:
2019-05-22 14:08:04 +08:00
```php
2019-05-22 14:41:16 +08:00
$orders = Db::table('order')
2019-05-22 14:08:04 +08:00
->orderByRaw('updated_at - created_at DESC')
->get();
```
2022-10-31 01:47:12 +08:00
## Join table
2019-05-22 14:08:04 +08:00
2019-05-22 14:41:16 +08:00
### Inner Join Clause
2022-10-31 01:47:12 +08:00
Query builders can also write `join` methods. To perform basic `"inner join"`, you can use the `join` method on the query builder instance. The first argument passed to the `join` method is the name of the table you want to join, while the other arguments use the field constraints that specify the join. You can also join multiple tables in a single query:
2019-05-22 14:41:16 +08:00
```php
$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
2022-10-31 01:47:12 +08:00
If you want to use `"left join"` or `"right join"` instead of `"inner join"`, use the `leftJoin` or `rightJoin` methods. These two methods are used in the same way as the `join` method:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
$users = Db::table('users')
->rightJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
```
2022-10-31 01:47:12 +08:00
### Cross Join Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Use the `crossJoin` method to do a `"cross join"` with the name of the table you want to join. A cross join produces a Cartesian product between the first table and the joined tables:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('sizes')
->crossJoin('colours')
->get();
```
2022-10-31 01:47:12 +08:00
### Advanced Join Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
You can specify more advanced `join` statements. For example passing a `closure` as the second parameter of the `join` method. This `closure` accepts a `JoinClause` object, specifying the constraints specified in the `join` statement:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
})
->get();
```
2022-10-31 01:47:12 +08:00
If you want to use `"where"` style statements on the join, you can use the `where` and `orWhere` methods on the join. These methods compare columns to values instead of columns to columns:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
```
2022-10-31 01:47:12 +08:00
### Subjoin query
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
You can use the `joinSub`, leftJoinSub` and `rightJoinSub` methods to join a query as a subquery. Each of their methods takes three parameters: a subquery, a table alias, and a closure that defines the associated fields:
2019-05-22 14:41:16 +08:00
```php
$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($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})->get();
```
2022-10-31 01:47:12 +08:00
## Combined query
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The query builder also provides a shortcut for "joining" two queries. For example, you can create a query first, then use the `union` method to union it with the second query:
2019-05-22 14:41:16 +08:00
```php
$first = Db::table('users')->whereNull('first_name');
$users = Db::table('users')
->whereNull('last_name')
->union($first)
->get();
```
2022-10-31 01:47:12 +08:00
## Where statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
### Simple Where Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
In constructing a `where` query instance, you can use the `where` method. The most basic way to call `where` is to pass three parameters: the first parameter is the column name, the second parameter is any operator supported by the database system, and the third parameter is the value to be compared for the column.
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
For example, here is a query to verify that the value of the gender field is equal to 1:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('user')->where('gender', '=', 1)->get();
```
2022-10-31 01:47:12 +08:00
For convenience, if you are simply comparing the column value to a given value, you can pass the value directly as the second parameter of the `where` method:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('user')->where('gender', 1)->get();
```
2022-10-31 01:47:12 +08:00
Of course, you can also use other operators to write where clauses:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->where('gender', '>=', 0)->get();
$users = Db::table('users')->where('gender', '<>', 1)->get();
$users = Db::table('users')->where('name', 'like', 'T%')->get();
```
2022-10-31 01:47:12 +08:00
You can also pass an array of conditions to the where function:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('user')->where([
['status', '=', '1'],
['gender', '=', '1'],
])->get();
```
2022-10-31 01:47:12 +08:00
### Or Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
You can chain `where` constraints together or add `or` clauses to the query. The `orWhere` method accepts the same parameters as the `where` method:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('user')
->where('gender', 1)
->orWhere('name', 'John')
->get();
```
2022-10-31 01:47:12 +08:00
### Other Where Statements
2019-05-22 14:41:16 +08:00
#### whereBetween
2022-10-31 01:47:12 +08:00
The `whereBetween` method verifies that the field value is between two given values:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->whereBetween('votes', [1, 100])->get();
```
#### whereNotBetween
2022-10-31 01:47:12 +08:00
The `whereNotBetween` method verifies that the field value is outside the given two values:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->whereNotBetween('votes', [1, 100])->get();
```
#### whereIn / whereNotIn
2022-10-31 01:47:12 +08:00
The `whereIn` method validates that the value of the field must exist in the specified array:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->whereIn('id', [1, 2, 3])->get();
```
2022-10-31 01:47:12 +08:00
The `whereNotIn` method verifies that the value of the field must not exist in the specified array:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->whereNotIn('id', [1, 2, 3])->get();
```
2022-10-31 01:47:12 +08:00
### Parameter grouping
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Sometimes you need to create more advanced `where` clauses, such as `"where exists"` or nested parameter groupings. The query builder can also handle these. Below, let's see an example of grouping constraints in parentheses:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->where('name', '=', 'John')
->where(function ($query) {
$query->where('votes', '>', 100)
->orWhere('title', '=', 'Admin');
})
->get();
```
2022-10-31 01:47:12 +08:00
As you can see, a `Closure` is written to the `where` method to construct a query builder to constrain a grouping. The `Closure` receives a query instance that you can use to set constraints that should be included. The above example will generate the following SQL:
2019-05-22 14:41:16 +08:00
```sql
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
```
2022-10-31 01:47:12 +08:00
> You should call this grouping with orWhere to avoid accidental application of global effects.
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
#### Where Exists Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The `whereExists` method allows you to use the `where exists SQL` statement. The `whereExists` method accepts a `Closure` parameter, the `whereExists` method accepts a `Closure` parameter, the closure takes a query builder instance allowing you to define queries placed in the `exists` clause:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->whereExists(function ($query) {
$query->select(Db::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
```
2022-10-31 01:47:12 +08:00
The above query will produce the following SQL statement:
2019-05-22 14:41:16 +08:00
```sql
select * from users
where exists (
select 1 from orders where orders.user_id = users.id
)
```
2022-10-31 01:47:12 +08:00
#### JSON Where Statement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
`Hyperf` also supports querying fields of type `JSON` (only on databases that support type `JSON`).
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->where('options->language', 'en')
->get();
$users = Db::table('users')
->where('preferences->dining->meal', 'salad')
->get();
```
2022-10-31 01:47:12 +08:00
You can also use `whereJsonContains` to query `JSON` arrays:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->whereJsonContains('options->languages', 'en')
->get();
```
2022-10-31 01:47:12 +08:00
You can use `whereJsonLength` to query the length of a `JSON` array:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->whereJsonLength('options->languages', 0)
->get();
$users = Db::table('users')
->whereJsonLength('options->languages', '>', 1)
->get();
```
## Ordering, Grouping, Limit, & Offset
### orderBy
2022-10-31 01:47:12 +08:00
The `orderBy` method allows you to order the result set by a given field. The first parameter of `orderBy` should be the field you want to sort, and the second parameter controls the direction of sorting, which can be `asc` or `desc`
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->orderBy('name', 'desc')
->get();
```
### latest / oldest
2022-10-31 01:47:12 +08:00
The `latest` and `oldest` methods allow you to easily sort by date. It uses the `created_at` column as the sort by default. Of course, you can also pass custom column names:
2019-05-22 14:41:16 +08:00
```php
$user = Db::table('users')->latest()->first();
```
### inRandomOrder
2022-10-31 01:47:12 +08:00
The `inRandomOrder` method is used to randomly order the results. For example, you can use this method to find a random user.
2019-05-22 14:41:16 +08:00
```php
$randomUser = Db::table('users')->inRandomOrder()->first();
```
### groupBy / having
2022-10-31 01:47:12 +08:00
The `groupBy` and `having` methods can group results. The use of the `having` method is very similar to the `where` method:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->groupBy('account_id')
->having('account_id', '>', 100)
->get();
```
2022-10-31 01:47:12 +08:00
You can pass multiple arguments to the `groupBy` method:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();
```
2022-10-31 01:47:12 +08:00
> For more advanced having syntax, see havingRaw method.
2019-05-22 14:41:16 +08:00
### skip / take
2022-10-31 01:47:12 +08:00
To limit the number of results returned, or to skip a specified number of results, you can use the `skip` and `take` methods:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->skip(10)->take(5)->get();
```
2022-10-31 01:47:12 +08:00
Or you can also use the limit and offset methods:
2019-05-22 14:41:16 +08:00
```php
$users = Db::table('users')->offset(10)->limit(5)->get();
```
2022-10-31 01:47:12 +08:00
## Conditional statements
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Sometimes you may want to execute a query only if the clause applies if a certain condition is true. For example, you might only want to apply a `where` statement if a given value exists in the request. You can do this by using the `when` method:
2019-05-22 14:41:16 +08:00
```php
$role = $request->input('role');
$users = Db::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
```
2022-10-31 01:47:12 +08:00
The `when` method executes the given closure only if the first argument is `true`. If the first argument is `false` , then the closure will not be executed
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
You can pass another closure as the third parameter of the `when` method. The closure will be executed if the first argument is `false`. To illustrate how to use this feature, let's configure the default ordering of a query:
2019-05-22 14:41:16 +08:00
```php
$sortBy = null;
$users = Db::table('users')
->when($sortBy, function ($query, $sortBy) {
return $query->orderBy($sortBy);
}, function ($query) {
return $query->orderBy('name');
})
->get();
```
2022-10-31 01:47:12 +08:00
## Insert
2019-05-22 14:08:04 +08:00
2022-10-31 01:47:12 +08:00
The query builder also provides the `insert` method for inserting records into the database. The `insert` method accepts an array of field names and field values for insertion:
2019-05-22 14:08:04 +08:00
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->insert(
['email' => 'john@example.com', 'votes' => 0]
);
```
2022-10-31 01:47:12 +08:00
You can even pass an array to the `insert` method to insert multiple records into the table
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->insert([
['email' => 'taylor@example.com', 'votes' => 0],
['email' => 'dayle@example.com', 'votes' => 0]
]);
```
2022-10-31 01:47:12 +08:00
### Auto Increment ID
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
If the table has an auto-incrementing `ID`, use the `insertGetId` method to insert the record and return the `ID` value
2019-05-22 14:41:16 +08:00
```php
$id = Db::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
```
2022-10-31 23:43:05 +08:00
## Update
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Of course, in addition to inserting records into the database, the query builder can also update existing records via the `update` method. The `update` method, like the `insert` method, accepts an array containing the fields and values to update. You can constrain the `update` query with the `where` clause:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->where('id', 1)->update(['votes' => 1]);
```
2022-10-31 23:43:05 +08:00
### Update or Insert
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Sometimes you may wish to update an existing record in the database, or create a matching record if it does not exist. In this case, the `updateOrInsert` method can be used. The `updateOrInsert` method accepts two parameters: an array of conditions to find the record, and an array of key-value pairs containing the record to update.
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The `updateOrInsert` method will first try to find a matching database record using the key and value pair of the first argument. If the record exists, use the value in the second parameter to update the record. If the record is not found, a new record is inserted, and the updated data is a collection of two arrays:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->updateOrInsert(
['email' => 'john@example.com', 'name' => 'John'],
['votes' => '2']
);
```
2022-10-31 01:47:12 +08:00
### Update JSON fields
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
When updating a JSON field, you can use the -> syntax to access the corresponding value in the JSON object, which is only supported on MySQL 5.7+:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->where('id', 1)->update(['options->enabled' => true]);
```
2022-10-31 01:47:12 +08:00
### Auto increment and decrement
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The query builder also provides convenience methods for incrementing or decrementing a given field. This method provides a more expressive and concise interface than manually writing `update` statements.
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
Both methods receive at least one parameter: the column that needs to be modified. The second parameter is optional and controls the amount by which the column is incremented or decremented:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->increment('votes');
Db::table('users')->increment('votes', 5);
Db::table('users')->decrement('votes');
Db::table('users')->decrement('votes', 5);
```
2022-10-31 01:47:12 +08:00
You can also specify fields to update during the operation:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->increment('votes', 1, ['name' => 'John']);
```
2022-10-31 01:47:12 +08:00
## Delete
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The query builder can also delete records from a table using the `delete` method. Before using `delete`, you can add a `where` clause to constrain the `delete` syntax:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->delete();
Db::table('users')->where('votes', '>', 100)->delete();
```
2022-10-31 01:47:12 +08:00
If you need to empty the table, you can use the `truncate` method, which will delete all rows and reset the auto-incrementing `ID` to zero:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->truncate();
```
2022-10-31 23:43:05 +08:00
## Pessimistic lock
2019-05-22 14:41:16 +08:00
2022-10-31 01:47:12 +08:00
The query builder also contains some functions that can help you implement `pessimistic locking` on the `select` syntax. To implement a `"shared lock"` in a query, you can use the `sharedLock` method. Shared locks prevent selected data columns from being tampered with until the transaction is committed
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->where('votes', '>', 100)->sharedLock()->get();
```
2022-10-31 01:47:12 +08:00
Alternatively, you can use the `lockForUpdate` method. Use the `"update"` lock to prevent rows from being modified or selected by other shared locks:
2019-05-22 14:41:16 +08:00
```php
Db::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
```
2019-05-22 14:08:04 +08:00