イントロダクションIntroduction
Laravelのデータベースクエリビルダは、データベースクエリを作成、実行するための便利で流暢(fluent)なインターフェイスを提供します。ほとんどのデータベース操作をアプリケーションで実行するために使用でき、Laravelがサポートするすべてのデータベースシステムで完全に機能します。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.
Laravelクエリビルダは、PDOパラメーターバインディングを使用して、SQLインジェクション攻撃からアプリケーションを保護します。クエリバインディングとしてクエリビルダに渡たす文字列をクリーンアップやサニタイズする必要はありません。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.
Note: {note} 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.
PDOはカラム名のバインドをサポートしていません。したがって、"order by"カラムを含む、クエリが参照するカラム名をユーザー入力で指定できないようにする必要があります。
データベースクエリの実行Running Database Queries
テーブルからの全行の取得Retrieving All Rows From A Table
DB
ファサードが提供するtable
メソッドを使用してクエリの最初に使用します。table
メソッドは、指定するテーブルの流暢(fluent)なクエリビルダインスタンスを返します。これによりクエリにさらに制約をチェーンし、最後にget
メソッドを使用してクエリの結果を取得できます。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:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
/**
* アプリケーションの全ユーザーをリスト表示
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
}
}
get
メソッドは、クエリの結果を含むIlluminate\Support\Collection
インスタンスを返します。各結果は、PHPのstdClass
オブジェクトのインスタンスです。オブジェクトのプロパティとしてカラムにアクセスすることにより、各カラムの値にアクセスできます。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:
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
foreach ($users as $user) {
echo $user->name;
}
コレクションのドキュメントをご覧ください。{tip} 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/{{version}}/collections].
">Tip!! Laravelコレクションは、データをマッピングや削減するためのさまざまなとても強力な方法を提供しています。Laravelコレクションの詳細は、
テーブルから単一の行/カラムを取得するRetrieving A Single Row / Column From A Table
データベーステーブルから単一の行だけを取得する必要がある場合は、DB
ファサードのfirst
メソッドを使用します。このメソッドは、単一のstdClass
オブジェクトを返します。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:
$user = DB::table('users')->where('name', 'John')->first();
return $user->email;
行全体が必要ない場合は、value
メソッドを使用してレコードから単一の値を抽出できます。このメソッドは、カラムの値を直接返します。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:
$email = DB::table('users')->where('name', 'John')->value('email');
id
列の値で単一の行を取得するには、find
メソッドを使用します。To retrieve a single row by its id
column value, use the find
method:
$user = DB::table('users')->find(3);
カラム値のリストの取得Retrieving A List Of Column Values
単一のカラムの値を含むIlluminate\Support\Collection
インスタンスを取得する場合は、pluck
メソッドを使用します。この例では、ユーザーのタイトルのコレクションを取得します。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:
use Illuminate\Support\Facades\DB;
$titles = DB::table('users')->pluck('title');
foreach ($titles as $title) {
echo $title;
}
pluck
メソッドに2番目の引数を指定し、結果のコレクションがキーとして使用する列を指定できます。You may specify the column that the resulting collection should use as its keys by providing a second argument to the pluck
method:
$titles = DB::table('users')->pluck('title', 'name');
foreach ($titles as $name => $title) {
echo $title;
}
結果の分割Chunking Results
何千ものデータベースレコードを処理する必要がある場合は、DB
ファサードが提供するchunk
メソッドの使用を検討してください。このメソッドは、一回に小さな結果のチャンク(小間切れ)を取得し、各チャンクをクロージャで処理するために送ります。たとえば、users
テーブル全体を一回で100レコードのチャンクで取得してみましょう。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:
use Illuminate\Support\Facades\DB;
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
foreach ($users as $user) {
//
}
});
クロージャから false
を返えせば、それ以上のチャンクの処理を停止できます。You may stop further chunks from being processed by returning false
from the closure:
DB::table('users')->orderBy('id')->chunk(100, function ($users) {
// レコードの処理…
return false;
});
結果をチャンク処理している途中にデータベースレコードを更新している場合、チャンクの結果が予期しない方法で変更される可能性があります。チャンク処理中に取得レコードが更新される場合は、代わりにchunkById
メソッドを使用するのが常に最善です。このメソッドは、レコードの主キーに基づいて結果を自動的にページ分割します。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:
DB::table('users')->where('active', false)
->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('users')
->where('id', $user->id)
->update(['active' => true]);
}
});
Note: {note} 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
lazy
メソッドは、チャンク単位でクエリを実行するという意味で、chunk
メソッドと似たような動作をします。しかし、各チャンクをコールバックに渡すのではなく、lazy()
メソッドは LazyCollection
を返し、結果をひとつのストリームとして扱えます。The lazy
method works similarly to the chunk
method[#chunking-results] 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/{{version}}/collections#lazy-collections], which lets you interact with the results as a single stream:
use Illuminate\Support\Facades\DB;
DB::table('users')->orderBy('id')->lazy()->each(function ($user) {
//
});
繰り返しになりますが、検索したレコードを反復しながら更新する予定がある場合は、代わりにlazyById
かlazyByIdDesc
メソッドの使用を推奨します。これらのメソッドは、レコードの主キーに基づいて結果を自動的にページ分割します。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:
DB::table('users')->where('active', false)
->lazyById()->each(function ($user) {
DB::table('users')
->where('id', $user->id)
->update(['active' => true]);
});
Note: {note} 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
クエリビルダは、count
、max
、min
、avg
、sum
などの集計値を取得するさまざまなメソッドも用意しています。クエリを作成した後、こうしたメソッドのどれでも呼び出すことができます。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:
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:
$price = DB::table('orders')
->where('finalized', 1)
->avg('price');
レコード存在の判定Determining If Records Exist
count
メソッドを使用して、クエリ制約に一致するレコードが存在するかどうかを判断する代わりに、exists
メソッドとdoesntExist
メソッドが使用できます。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:
if (DB::table('orders')->where('finalized', 1)->exists()) {
// ...
}
if (DB::table('orders')->where('finalized', 1)->doesntExist()) {
// ...
}
SELECT文Select Statements
SELECT句の指定Specifying A Select Clause
データベーステーブルからすべての列を選択する必要があるとは限りません。select
メソッドを使用して、クエリにカスタムの"select"句を指定できます。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:
use Illuminate\Support\Facades\DB;
$users = DB::table('users')
->select('name', 'email as user_email')
->get();
distinct
メソッドを使用すると、クエリにダブりのない結果を返すように強制できます。The distinct
method allows you to force the query to return distinct results:
$users = DB::table('users')->distinct()->get();
クエリビルダインスタンスがすでにあり、既存のSELECT句にカラムを追加する場合は、addSelect
メソッドを使用できます。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:
$query = DB::table('users')->select('name');
$users = $query->addSelect('age')->get();
素のSQLRaw Expressions
クエリへ任意の文字列を挿入する必要のある場合があります。素の文字列式を作成するには、DB
ファサードが提供するraw
メソッドを使用します。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:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
Note: {note} Raw statements will be injected into the query as strings, so you should be extremely careful to avoid creating SQL injection vulnerabilities.
素のSQL文はそのまま文字列としてクエリへ挿入されるため、SQLインジェクションの脆弱性を含めぬように細心の注意を払う必要があります。
rawメソッドRaw Methods
DB::raw
メソッドを使用する代わりに以降のメソッドを使用して、クエリのさまざまな部分に素のSQL式を挿入することもできます。素の式を使用するクエリでは、SQLインジェクションの脆弱性からの保護をLaravelは保証しないことに注意してください。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 can not guarantee that any query using raw expressions is protected against SQL injection vulnerabilities.
selectRaw
selectRaw
addSelect(DB::raw(...))
の代わりにselectRaw
メソッドを使用できます。このメソッドは、2番目の引数にバインディングのオプションの配列を取ります。The selectRaw
method can be used in place of addSelect(DB::raw(...))
. This method accepts an optional array of bindings as its second argument:
$orders = DB::table('orders')
->selectRaw('price * ? as price_with_tax', [1.0825])
->get();
whereRaw/orWhereRaw
whereRaw / orWhereRaw
whereRaw
メソッドとorWhereRaw
メソッドを使用して、素の"where"句をクエリに挿入できます。これらのメソッドは、2番目の引数にバインディングのオプションの配列を取ります。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:
$orders = DB::table('orders')
->whereRaw('price > IF(state = "TX", ?, 100)', [200])
->get();
havingRaw/orHavingRaw
havingRaw / orHavingRaw
havingRaw
メソッドとorHavingRaw
メソッドを使用して、"having"句の値として素の文字列を指定できます。これらのメソッドは、2番目の引数にバインディングのオプションの配列を取ります。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:
$orders = DB::table('orders')
->select('department', DB::raw('SUM(price) as total_sales'))
->groupBy('department')
->havingRaw('SUM(price) > ?', [2500])
->get();
orderByRaw
orderByRaw
orderByRaw
メソッドを使用して、"order by"句の値として素の文字列を指定できます。The orderByRaw
method may be used to provide a raw string as the value of the "order by" clause:
$orders = DB::table('orders')
->orderByRaw('updated_at - created_at DESC')
->get();
groupByRaw
groupByRaw
groupByRaw
メソッドを使用して、groupby
句の値として素の文字列を指定できます。The groupByRaw
method may be used to provide a raw string as the value of the group by
clause:
$orders = DB::table('orders')
->select('city', 'state')
->groupByRaw('city, state')
->get();
JOINJoins
INNER JOIN句Inner Join Clause
クエリビルダを使用して、クエリにJOIN句を追加することもできます。基本的な"inner join"を実行するには、クエリビルダインスタンスでjoin
メソッドを使用します。join
メソッドに渡す最初の引数は、結合するテーブルの名前であり、残りの引数は、結合のカラム制約を指定します。1つのクエリで複数のテーブルと結合することもできます。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:
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句Left Join / Right Join Clause
"inner join"の代わりに"left join"や"right join"を実行する場合は、leftJoin
かrightJoin
メソッドを使用します。これらのメソッドはjoin
メソッドと同じ引数を取ります。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:
$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句Cross Join Clause
crossJoin
メソッドを使用して、"cross join"を実行できます。クロス結合は、最初のテーブルと結合するテーブルとの間のデカルト積を生成します。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:
$sizes = DB::table('sizes')
->crossJoin('colors')
->get();
上級JOIN句Advanced Join Clauses
より高度なJOIN句を指定することもできます。そのためには、join
メソッドの2番目の引数にクロージャを渡します。クロージャはIlluminate\Database\Query\JoinClause
インスタンスを受け取ります。これにより、"join"句に制約を指定できます。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:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')->orOn(...);
})
->get();
テーブル結合で"where"句を使用する場合は、JoinClause
インスタンスが提供するwhere
とorWhere
メソッドを使用します。2つのカラムを比較する代わりに、これらのメソッドはカラムを値と比較します。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:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
サブクエリのJOINSubquery Joins
joinSub
、leftJoinSub
、rightJoinSub
メソッドを使用して、クエリをサブクエリに結合できます。各メソッドは、サブクエリ、そのテーブルエイリアス、および関連するカラムを定義するクロージャの3引数を取ります。この例では、各ユーザーレコードにユーザーの最後に公開されたブログ投稿のcreated_at
タイムスタンプも含まれているユーザーのコレクションを取得しています。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:
$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();
UNIONUnions
クエリビルダは、2つ以上のクエリを「結合(union)」するために便利な方法も提供します。たとえば、最初のクエリを作成したあとで、union
メソッドを使用してより多くのクエリを結合できます。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:
use Illuminate\Support\Facades\DB;
$first = DB::table('users')
->whereNull('first_name');
$users = DB::table('users')
->whereNull('last_name')
->union($first)
->get();
union
メソッドに加えて、クエリビルダではunionAll
メソッドも提供しています。unionAll
メソッドを使用して結合されたクエリでは、重複する結果は削除されません。unionAll
メソッドは、union
メソッドと同じメソッド引数です。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.
基本WHERE句Basic Where Clauses
Where句Where Clauses
クエリビルダのwhere
メソッドを使用して、クエリに"where"句を追加できます。where
メソッドのもっとも基本的な呼び出しには、3つの引数が必要です。最初の引数はカラムの名前です。2番目の引数は演算子であり、データベースがサポートしている任意の演算子が指定できます。3番目の引数はカラムの値と比較する値です。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.
たとえば、以下のクエリはvotes
列の値が100
に等しく、age
列の値が35
より大きいユーザーを取得します。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
:
$users = DB::table('users')
->where('votes', '=', 100)
->where('age', '>', 35)
->get();
使いやすいように、カラムが特定の値に対して=
であることを確認する場合は、その値を2番目の引数としてwhere
メソッドに渡すことができます。Laravelは、=
演算子を使用したと扱います。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:
$users = DB::table('users')->where('votes', 100)->get();
前述のように、データベースシステムがサポートしている任意の演算子を使用できます。As previously mentioned, you may use any operator that is supported by your database system:
$users = DB::table('users')
->where('votes', '>=', 100)
->get();
$users = DB::table('users')
->where('votes', '<>', 100)
->get();
$users = DB::table('users')
->where('name', 'like', 'T%')
->get();
条件の配列をwhere
関数に渡すこともできます。配列の各要素は、通常where
メソッドに渡す3つの引数を含む配列である必要があります。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:
$users = DB::table('users')->where([
['status', '=', '1'],
['subscribed', '<>', '1'],
])->get();
Note: {note} 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.
PDOはカラム名のバインドをサポートしていません。したがって、"order by"カラムを含め、クエリが参照するカラム名をユーザーの入力で決定することは絶対に避けてください。
OR WHERE句Or Where Clauses
クエリビルダのwhere
メソッドへの呼び出しをチェーン化する場合、"where"句はand
演算子を使用して結合されます。ただし、orWhere
メソッドを使用して、or
演算子を使用して句をクエリに結合することもできます。orWhere
メソッドはwhere
メソッドと同じ引数を受け入れます。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:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere('name', 'John')
->get();
括弧内に"or"条件をグループ化する必要がある場合は、orWhere
メソッドの最初の引数としてクロージャを渡してください。If you need to group an "or" condition within parentheses, you may pass a closure as the first argument to the orWhere
method:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere(function($query) {
$query->where('name', 'Abigail')
->where('votes', '>', 50);
})
->get();
上記の例では、以下のSQLを生成します。The example above will produce the following SQL:
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
Note:
グローバルスコープを適用する場合の予期しない動作を回避するために、常にorWhere
呼び出しをグループ化する必要があります。{note} You should always grouporWhere
calls in order to avoid unexpected behavior when global scopes are applied.
JSON WHERE句JSON Where Clauses
Laravelは、JSONカラムタイプのサポートを提供するデータベースで、JSONカラムタイプのクエリもサポートしています。現在、こうしたデータベースはMySQL5.7以上、PostgreSQL、SQL Server 2016、SQLite3.9.0(JSON1拡張機能を使用)があります。JSONカラムをクエリするには、->
演算子を使用します。Laravel also supports querying JSON column types on databases that provide support for JSON column types. Currently, this includes MySQL 5.7+, PostgreSQL, SQL Server 2016, and SQLite 3.9.0 (with the JSON1 extension[https://www.sqlite.org/json1.html]). To query a JSON column, use the ->
operator:
$users = DB::table('users')
->where('preferences->dining->meal', 'salad')
->get();
whereJsonContains
を使用してJSON配列をクエリできます。この機能はSQLiteデータベースではサポートされていません。You may use whereJsonContains
to query JSON arrays. This feature is not supported by the SQLite database:
$users = DB::table('users')
->whereJsonContains('options->languages', 'en')
->get();
アプリケーションがMySQLまたはPostgreSQLデータベースを使用している場合は、値の配列をwhereJsonContains
メソッドで渡してください。If your application uses the MySQL or PostgreSQL databases, you may pass an array of values to the whereJsonContains
method:
$users = DB::table('users')
->whereJsonContains('options->languages', ['en', 'de'])
->get();
whereJsonLength
メソッドを使用して、JSON配列をその長さでクエリできます。You may use whereJsonLength
method to query JSON arrays by their length:
$users = DB::table('users')
->whereJsonLength('options->languages', 0)
->get();
$users = DB::table('users')
->whereJsonLength('options->languages', '>', 1)
->get();
その他のWHERE句Additional Where Clauses
whereBetween/orWhereBetweenwhereBetween / orWhereBetween
whereBetween
メソッドは、カラムの値が2つの値の間にある条件を加えます。The whereBetween
method verifies that a column's value is between two values:
$users = DB::table('users')
->whereBetween('votes', [1, 100])
->get();
whereNotBetween/orWhereNotBetweenwhereNotBetween / orWhereNotBetween
whereNotBetween
メソッドは、カラムの値が2つの値間にない条件を加えます。The whereNotBetween
method verifies that a column's value lies outside of two values:
$users = DB::table('users')
->whereNotBetween('votes', [1, 100])
->get();
whereIn/whereNotIn/orWhereIn/orWhereNotInwhereIn / whereNotIn / orWhereIn / orWhereNotIn
whereIn
メソッドは、特定のカラム値が指定した配列内に含まれる条件を加えます。The whereIn
method verifies that a given column's value is contained within the given array:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
whereNotIn
メソッドは、特定のカラム値が指定した配列に含まれない条件を加えます。The whereNotIn
method verifies that the given column's value is not contained in the given array:
$users = DB::table('users')
->whereNotIn('id', [1, 2, 3])
->get();
Note:
クエリに整数バインディングの大きな配列を追加する場合は、whereIntegerInRaw
またはwhereIntegerNotInRaw
メソッドを使用してメモリ使用量を大幅に削減できます。{note} If you are adding a large array of integer bindings to your query, thewhereIntegerInRaw
orwhereIntegerNotInRaw
methods may be used to greatly reduce your memory usage.
whereNull/whereNotNull/orWhereNull/orWhereNotNullwhereNull / whereNotNull / orWhereNull / orWhereNotNull
whereNull
メソッドは、指定したカラムの値がNULL
である条件を加えます。The whereNull
method verifies that the value of the given column is NULL
:
$users = DB::table('users')
->whereNull('updated_at')
->get();
whereNotNull
メソッドは、カラムの値がNULL
ではないことを確認します。The whereNotNull
method verifies that the column's value is not NULL
:
$users = DB::table('users')
->whereNotNull('updated_at')
->get();
whereDate / whereMonth / whereDay / whereYear / whereTimewhereDate / whereMonth / whereDay / whereYear / whereTime
whereDate
メソッドを使用して、カラム値を日付と比較できます。The whereDate
method may be used to compare a column's value against a date:
$users = DB::table('users')
->whereDate('created_at', '2016-12-31')
->get();
whereMonth
メソッドを使用して、カラム値を特定の月と比較できます。The whereMonth
method may be used to compare a column's value against a specific month:
$users = DB::table('users')
->whereMonth('created_at', '12')
->get();
whereDay
メソッドを使用して、カラム値を月の特定の日と比較できます。The whereDay
method may be used to compare a column's value against a specific day of the month:
$users = DB::table('users')
->whereDay('created_at', '31')
->get();
whereYear
メソッドを使用して、カラム値を特定の年と比較できます。The whereYear
method may be used to compare a column's value against a specific year:
$users = DB::table('users')
->whereYear('created_at', '2016')
->get();
whereTime
メソッドを使用して、カラム値を特定の時間と比較できます。The whereTime
method may be used to compare a column's value against a specific time:
$users = DB::table('users')
->whereTime('created_at', '=', '11:20:45')
->get();
whereColumn/orWhereColumnwhereColumn / orWhereColumn
whereColumn
メソッドは、2つのカラムが等しい条件を加えます。The whereColumn
method may be used to verify that two columns are equal:
$users = DB::table('users')
->whereColumn('first_name', 'last_name')
->get();
比較演算子を whereColumn
メソッドに渡すこともできます。You may also pass a comparison operator to the whereColumn
method:
$users = DB::table('users')
->whereColumn('updated_at', '>', 'created_at')
->get();
カラム比較の配列をwhereColumn
メソッドに渡すこともできます。これらの条件は、and
演算子を使用して結合されます。You may also pass an array of column comparisons to the whereColumn
method. These conditions will be joined using the and
operator:
$users = DB::table('users')
->whereColumn([
['first_name', '=', 'last_name'],
['updated_at', '>', 'created_at'],
])->get();
論理グループ化Logical Grouping
クエリを論理的にグループ化するため、括弧内のいくつかの"where"句をグループ化したい場合があります。実際、予期外のクエリ動作を回避するため、orWhere
メソッドへの呼び出しを通常は常に括弧内へグループ化する必要があります。これには、where
メソッドにクロージャを渡します。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:
$users = DB::table('users')
->where('name', '=', 'John')
->where(function ($query) {
$query->where('votes', '>', 100)
->orWhere('title', '=', 'Admin');
})
->get();
ご覧のとおり、クロージャをwhere
メソッドへ渡すことで、クエリビルダへ制約のグループ化を開始するように指示しています。クロージャは、括弧グループ内に含める必要のある制約を構築するために使用するクエリビルダインスタンスを受け取ります。上記の例では、次のSQLが生成されます。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:
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
Note:
グローバルスコープが適用されたときの予想外の動作を回避するために、常にorWhere
呼び出しをグループ化する必要があります。{note} You should always grouporWhere
calls in order to avoid unexpected behavior when global scopes are applied.
上級WHERE節Advanced Where Clauses
WHERE EXISTS句Where Exists Clauses
whereExists
メソッドを使用すると、"where exists"SQL句を記述できます。whereExists
メソッドは、クエリビルダインスタンスを受け取るクロージャを引数に取り、"exists"句内へ配置するクエリを定義します。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:
$users = DB::table('users')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('orders')
->whereColumn('orders.user_id', 'users.id');
})
->get();
上記のクエリは、以下のSQLを生成します。The query above will produce the following SQL:
select * from users
where exists (
select 1
from orders
where orders.user_id = users.id
)
サブクエリWHERE句Subquery Where Clauses
サブクエリの結果を特定の値と比較する"where"句を作成したい場合があるでしょう。これには、クロージャと値をwhere
メソッドへ渡してください。たとえば、以下のクエリは、特定のタイプの最近の「メンバーシップ(membership)」を持つすべてのユーザーを取得します。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;
use App\Models\User;
$users = User::where(function ($query) {
$query->select('type')
->from('membership')
->whereColumn('membership.user_id', 'users.id')
->orderByDesc('membership.start_date')
->limit(1);
}, 'Pro')->get();
もしくは、カラムをサブクエリの結果と比較する"where"句を作成したい場合もあるでしょう。これは、カラム、演算子、およびクロージャをwhere
メソッドに渡すことで実現できます。たとえば、次のクエリは、金額が平均より少ないすべての収入レコードを取得します。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;
use App\Models\Income;
$incomes = Income::where('amount', '<', function ($query) {
$query->selectRaw('avg(i.amount)')->from('incomes as i');
})->get();
順序、グループ化、件数制限、オフセットOrdering, Grouping, Limit & Offset
順序Ordering
orderBy
メソッドThe orderBy
Method
orderBy
メソッドを使用すると、クエリの結果を特定のカラムで並べ替えできます。orderBy
メソッドの最初の引数は、並べ替えるカラムです。2番目の引数は、並べ替えの方向を決定し、asc
またはdesc
のいずれかです。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
:
$users = DB::table('users')
->orderBy('name', 'desc')
->get();
複数の列で並べ替えるには、必要な回数のorderBy
を呼び出すだけです。To sort by multiple columns, you may simply invoke orderBy
as many times as necessary:
$users = DB::table('users')
->orderBy('name', 'desc')
->orderBy('email', 'asc')
->get();
latest
とoldest
メソッドThe latest
& oldest
Methods
latest
およびoldest
メソッドを使用すると、結果を日付順に簡単に並べ替えできます。デフォルトでは、結果をテーブルのcreated_at
カラムによって順序付けします。もしくは、並べ替えるカラム名を渡すこともできます。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:
$user = DB::table('users')
->latest()
->first();
ランダム順Random Ordering
inRandomOrder
メソッドを使用して、クエリ結果をランダムに並べ替えできます。たとえば、このメソッドを使用して、ランダムにユーザーをフェッチできます。The inRandomOrder
method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
既存の順序の削除Removing Existing Orderings
reorder
メソッドは、以前にクエリへ指定したすべての"order by"句を削除します。The reorder
method removes all of the "order by" clauses that have previously been applied to the query:
$query = DB::table('users')->orderBy('name');
$unorderedUsers = $query->reorder()->get();
reorder
メソッドを呼び出すときにカラムと方向を渡して、既存の"order by"句をすべて削除しから、クエリにまったく新しい順序を適用することもできます。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:
$query = DB::table('users')->orderBy('name');
$usersOrderedByEmail = $query->reorder('email', 'desc')->get();
グループ化Grouping
groupBy
とhaving
メソッドThe groupBy
& having
Methods
ご想像のとおり、groupBy
メソッドとhaving
メソッドを使用してクエリ結果をグループ化できます。having
メソッドの引数はwhere
メソッドの引数の使い方に似ています。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:
$users = DB::table('users')
->groupBy('account_id')
->having('account_id', '>', 100)
->get();
havingBetween`メソッドを使うと、指定した範囲内の結果をフィルタリングできます。You can use the havingBetween
method to filter the results within a given range:
$report = DB::table('orders')
->selectRaw('count(id) as number_of_orders, customer_id')
->groupBy('customer_id')
->havingBetween('number_of_orders', [5, 15])
->get();
groupBy
メソッドに複数の引数を渡して、複数のカラムでグループ化できます。You may pass multiple arguments to the groupBy
method to group by multiple columns:
$users = DB::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();
より高度なhaving
ステートメントを作成するには、havingRaw
メソッドを参照してください。To build more advanced having
statements, see the havingRaw
[#raw-methods] method.
件数制限とオフセットLimit & Offset
skip
とtake
メソッドThe skip
& take
Methods
skip
メソッドとtake
メソッドを使用して、クエリから返される結果の数を制限したり、クエリ内の特定の数の結果をスキップしたりできます。You may use the skip
and take
methods to limit the number of results returned from the query or to skip a given number of results in the query:
$users = DB::table('users')->skip(10)->take(5)->get();
または、limit
メソッドとoffset
メソッドを使用することもできます。これらのメソッドは、それぞれ「take」メソッドと「skip」メソッドと機能的に同等です。Alternatively, you may use the limit
and offset
methods. These methods are functionally equivalent to the take
and skip
methods, respectively:
$users = DB::table('users')
->offset(10)
->limit(5)
->get();
条件節Conditional Clauses
特定のクエリ句を別の条件に基づいてクエリに適用したい場合があります。たとえば、指定された入力値が受信HTTPリクエストに存在する場合にのみ、where
ステートメントを適用したい場合です。これは、when
メソッドを使用して実現可能です。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:
$role = $request->input('role');
$users = DB::table('users')
->when($role, function ($query, $role) {
return $query->where('role_id', $role);
})
->get();
when
メソッドは、最初の引数がtrue
の場合にのみ、指定されたクロージャを実行します。最初の引数がfalse
の場合、クロージャは実行されません。したがって、上記の例では、when
メソッドに指定されたクロージャは、role
フィールドが受信リクエストに存在し、true
と評価された場合にのみ呼び出されます。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
.
when
メソッドの3番目の引数として別のクロージャを渡すことができます。このクロージャは、最初の引数が「false」と評価された場合にのみ実行されます。この機能の使用方法を説明するために、クエリのデフォルトの順序を設定してみます。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:
$sortByVotes = $request->input('sort_by_votes');
$users = DB::table('users')
->when($sortByVotes, function ($query, $sortByVotes) {
return $query->orderBy('votes');
}, function ($query) {
return $query->orderBy('name');
})
->get();
INSERT文Insert Statements
クエリビルダは、データベーステーブルにレコードを挿入するために使用できるinsert
メソッドも提供します。insert
メソッドは、カラム名と値の配列を引数に取ります。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:
DB::table('users')->insert([
'email' => 'kayla@example.com',
'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:
DB::table('users')->insert([
['email' => 'picard@example.com', 'votes' => 0],
['email' => 'janeway@example.com', 'votes' => 0],
]);
insertOrIgnore
メソッドは、データベースにレコードを挿入するときにエラーを無視します。The insertOrIgnore
method will ignore errors while inserting records into the database:
DB::table('users')->insertOrIgnore([
['id' => 1, 'email' => 'sisko@example.com'],
['id' => 2, 'email' => 'archer@example.com'],
]);
Note:
insertOrIgnore
は重複レコードを無視し、データベースエンジンにより他のタイプのエラーも無視します。たとえば、insertOrIgnore
は [MySQLのstrictモードをバイパス]します(https://dev.mysql.com/doc/refman/en/sql-mode.html#ignore-effect-on-execution)。{note}insertOrIgnore
will ignore duplicate records and also may ignore other types of errors 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].
自動増分IDAuto-Incrementing IDs
テーブルに自動増分IDがある場合は、insertGetId
メソッドを使用してレコードを挿入してから、IDを取得します。If the table has an auto-incrementing id, use the insertGetId
method to insert a record and then retrieve the ID:
$id = DB::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
Note:
PostgreSQLを使用する場合、insertGetId
メソッドは自動増分カラムがid
という名前であると想定します。別の「シーケンス」からIDを取得する場合は、insertGetId
メソッドの第2パラメータとしてカラム名を渡してください。{note} When using PostgreSQL theinsertGetId
method expects the auto-incrementing column to be namedid
. If you would like to retrieve the ID from a different "sequence", you may pass the column name as the second parameter to theinsertGetId
method.
UPSERTSUpserts
upsert
(update+insert)メソッドは、存在しない場合はレコードを挿入し、指定した新しい値でレコードを更新します。メソッドの最初の引数は、挿入または更新する値で構成され、2番目の引数は、関連付けたテーブル内のレコードを一意に識別するカラムをリストします。第3引数は、一致するレコードがデータベースですでに存在する場合に、更新する必要があるカラムの配列です。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:
DB::table('flights')->upsert([
['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],
['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]
], ['departure', 'destination'], ['price']);
上記の例では、Laravelは2つのレコードを挿入しようとします。同じdeparture
カラムとdestination
カラムの値を持つレコードがすでに存在する場合、Laravelはそのレコードの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.
Note:
SQL Serverを除くすべてのデータベースでは、upsert
メソッドの2番目の引数のカラムに「プライマリ」または「ユニーク」インデックスが必要です。また、MySQLデータベースドライバは、upert
メソッドの第2引数を無視し、常にテーブルの「プライマリ」および「ユニーク」インデックスを使用して既存のレコードを検出します。{note} All databases except SQL Server require the columns in the second argument of theupsert
method to have a "primary" or "unique" index. In addition, the MySQL database driver ignores the second argument of theupsert
method and always uses the "primary" and "unique" indexes of the table to detect existing records.
UPDATE文Update Statements
データベースにレコードを挿入することに加え、クエリビルダはupdate
メソッドを使用して既存のレコードを更新することもできます。update
メソッドは、insert
メソッドと同様に、更新するカラムを示すカラムと値のペアの配列を受け入れます。update
メソッドは、影響を受けた行数を返します。where
句を使用してupdate
クエリを制約できます。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:
$affected = DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
UpdateかInsertUpdate Or Insert
データベース内の既存のレコードを更新、もしくは一致するレコードが存在しない場合は作成したい場合もあるでしょう。このシナリオでは、updateOrInsert
メソッドを使用できます。updateOrInsert
メソッドは、2つの引数を受け入れます。レコードを検索するための条件の配列と、更新するカラムを示すカラムと値のペアの配列です。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.
updateOrInsert
メソッドは、最初の引数のカラムと値のペアを使用して、一致するデータベースレコードを見つけようとします。レコードが存在する場合は、2番目の引数の値で更新します。レコードが見つからない場合は、両方の引数の属性をマージした新しいレコードを挿入します。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 can not be found, a new record will be inserted with the merged attributes of both arguments:
DB::table('users')
->updateOrInsert(
['email' => 'john@example.com', 'name' => 'John'],
['votes' => '2']
);
JSONカラムの更新Updating JSON Columns
JSONカラムを更新するときは、->
構文を使用してJSONオブジェクトの適切なキーを更新する必要があります。この操作は、MySQL5.7以上およびPostgreSQL9.5以上でサポートされています。When updating a JSON column, you should use ->
syntax to update the appropriate key in the JSON object. This operation is supported on MySQL 5.7+ and PostgreSQL 9.5+:
$affected = DB::table('users')
->where('id', 1)
->update(['options->enabled' => true]);
増分と減分Increment & Decrement
クエリビルダは、特定のカラムの値を増分または減分するための便利なメソッドも提供します。これらのメソッドは両方とも、少なくとも1つの引数(変更するカラム)を受け入れます。カラムを増分/減分する量を指定するために、2番目の引数を指定できます。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:
DB::table('users')->increment('votes');
DB::table('users')->increment('votes', 5);
DB::table('users')->decrement('votes');
DB::table('users')->decrement('votes', 5);
この操作中に、ついでに更新するカラムを指定することもできます。You may also specify additional columns to update during the operation:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
DELETE文Delete Statements
クエリビルダのdelete
メソッドを使用して、テーブルからレコードを削除できます。delete
メソッドは影響を受けた行数を返します。delete
メソッドを呼び出す前に"where"句を追加することで、delete
ステートメントを制約できます。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:
$deleted = DB::table('users')->delete();
$deleted = DB::table('users')->where('votes', '>', 100)->delete();
テーブル全体を切り捨てて、テーブルからすべてのレコードを削除し、自動増分IDをゼロにリセットする場合は、truncate
メソッドを使用します。If you wish to truncate an entire table, which will remove all records from the table and reset the auto-incrementing ID to zero, you may use the truncate
method:
DB::table('users')->truncate();
テーブルのトランケーションとPostgreSQLTable Truncation & PostgreSQL
PostgreSQLデータベースを切り捨てる場合、CASCADE
動作が適用されます。これは、他のテーブルのすべての外部キー関連レコードも削除されることを意味します。When truncating a PostgreSQL database, the CASCADE
behavior will be applied. This means that all foreign key related records in other tables will be deleted as well.
悲観的ロックPessimistic Locking
クエリビルダには、select
ステートメントを実行するときに「悲観的ロック」を行うために役立つ関数も含まれています。「共有ロック」を使用してステートメントを実行するには、sharedLock
メソッドを呼び出すことができます。共有ロックは、トランザクションがコミットされるまで、選択した行が変更されないようにします。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:
DB::table('users')
->where('votes', '>', 100)
->sharedLock()
->get();
または、lockForUpdate
メソッドを使用することもできます。「更新用」ロックは、選択したレコードが変更されたり、別の共有ロックで選択されたりするのを防ぎます。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:
DB::table('users')
->where('votes', '>', 100)
->lockForUpdate()
->get();
デバッグDebugging
クエリの作成中にdd
メソッドとdump
メソッドを使用して、現在のクエリバインディングとSQLをダンプできます。dd
メソッドはデバッグ情報を表示してから、リクエストの実行を停止します。dump
メソッドはデバッグ情報を表示しますが、リクエストの実行を継続できます。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:
DB::table('users')->where('votes', '>', 100)->dd();
DB::table('users')->where('votes', '>', 100)->dump();