Lang x Lang

Database: Getting Started

Table of Contents

Introduction

ほぼ全ての現代の web application は、 database とやり取りを行います。 Laravel は、生の SQL、流れるような query builder、そしてEloquent ORMを使用して、さまざまなサポートされているデータベースとの対話を非常に簡単にします。現在、 Laravel は 5 つのデータベースに対して一次サポートを提供しています:

Configuration

Laravel の database services の設定は、アプリケーションのconfig/database.php設定ファイルに置かれています。このファイルでは、すべての database 接続を定義するとともに、どの connection を default として使用するべきかを指定することもできます。このファイル内の設定 options のほとんどは、アプリケーションの environment 変数の values によって制御されています。このファイルには、Laravel がサポートしているほとんどの database システムの例が提供されています。

default として、Laravel のサンプル環境設定は、ローカルマシンで Laravel applications を development するための Docker 設定であるLaravel Sailを使用する準備ができています。しかし、ローカルの database に必要な設定を自由に変更することができます。

SQLite 設定

SQLite データベースは、ファイルシステム上の single ファイルに格納されています。端末のtouch command を使用して、新しい SQLite database を作成することができます:touch database/database.sqlite。 database が作成された後、DB_DATABASE environment 変数に database への絶対 path を指定することにより、この database へ簡単に environment 変数を設定できます。

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

default で、SQLite 接続に対する外部キー制約が有効になっています。それらを無効にしたい場合は、DB_FOREIGN_KEYS environment variables をfalseに設定するべきです:

DB_FOREIGN_KEYS=false

NOTE

Laravel インストーラを使用して Laravel アプリケーションを作成し、SQLite を database として選択すると、Laravel は自動的にdatabase/database.sqliteファイルを作成し、あなたのために default のdata ベース migrationを実行します。

Microsoft SQL Server の構成

Microsoft SQL Server の database を使用するには、sqlsrvおよびpdo_sqlsrv PHP エクステンションがインストールされており、それらが必要とする依存関係がすべて満たされていること、例えば、Microsoft SQL ODBC の driver などを確認してください。

URL を使用した設定

通常、database 接続はhostdatabaseusernamepassword、etc などの複数の設定 values を使用して構成されます。これらの各設定 values にはそれぞれ対応する environment 変数があります。これは、production サーバーで database connection 情報を設定する際に、複数の environment 変数を管理する必要があることを意味します。

いくつかの管理された database providers 、例えば AWS や Heroku は、"URL"内にすべての connection 情報を含む一つの single database を提供します。" database の全体の情報が single string で記述されています。 その一例として、以下のような database URL が考えられます。

mysql://root:password@127.0.0.1/forge?charset=UTF-8

これらの URL は通常、標準的な schema の慣習に従っています:

driver://username:password@host:port/database?options

便宜上、Laravel は複数の設定 options を使用して database を構成する代わりに、これらの URL をサポートしています。url(または対応するDB_URL environment 変数)設定オプションが存在する場合、それは database connection および認証情報を抽出するために使用されます。

読み書きの接続

時折、あなたは SELECT 文に対して一つの database connection を使用し、他の INSERT 、 UPDATE 、そして DELETE 文には別のものを使用したいと思うかもしれません。 Laravel ではこれが breeze であり、生のクエリを使用しているか、 query ビルダーを使用しているか、または Eloquent ORM を使用しているかに関わらず、常に適切な接続が使用されます。

read / write 接続がどのように設定されるべきかを確認するために、この例を見てみましょう:

'mysql' => [
    'read' => [
        'host' => [
            '192.168.1.1',
            '196.168.1.2',
        ],
    ],
    'write' => [
        'host' => [
            '196.168.1.3',
        ],
    ],
    'sticky' => true,

    'database' => env('DB_DATABASE', 'laravel'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => env('DB_CHARSET', 'utf8mb4'),
    'collation' => env('DB_COLLATION', 'utf8mb4_0900_ai_ci'),
    'prefix' => '',
    'prefix_indexes' => true,
    'strict' => true,
    'engine' => null,
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
    ]) : [],
],

設定の array には三つの keys が追加されていることに注意してください:readwrite、およびstickyです。readwriteの keys は、 single のキーを含む array values を持っています:hostreadwriteの接続のための残りの database options は、主要なmysql設定の array からマージされます。

メインのmysql array から values を上書きしたい場合のみ、readwriteの配列にアイテムを配置する必要があります。したがって、この場合、192.168.1.1は"read" connection 用のホストとして使用され、192.168.1.3は"write" connection 用として使用されます。database の資格情報、プレフィックス、文字セット、およびその他の options はメインのmysql array で両方の接続間で共有されます。host設定 array に複数の values が存在する場合、database ホストは各 request ごとにランダムに選択されます。

stickyオプション

stickyオプションは、オプショナルな value で、現在の request サイクル中に database に書き込まれたレコードを即座に読み取ることを許可するために使用できます。stickyオプションが有効になっていて、現在の request サイクル中に database に対して"write"操作が行われた場合、任意のさらなる"read"操作は"write" connection を使用します。これにより、 request サイクル中に書き込まれた任意の data を、その同じ request の間に database から直ちに読み戻すことができます。これがあなたの application にとって望ましい動作であるかどうかは、あなたが判断することです。

Running SQL Queries

database 接続を設定したら、DB facade を使ってクエリを実行できます。DB facade は、各種類の query:selectupdateinsertdelete、そしてstatement用の methods を提供しています。

Select Query の実行

基本的な SELECT query を実行するためには、DB facade のselect method を利用することができます:

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
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::select('select * from users where active = ?', [1]);

        return view('user.index', ['users' => $users]);
    }
}

selectの method へ渡される最初の引数は、SQL の query であり、2 番目の引数は、 query にバインドする必要があるパラメーター・バインディングです。通常、これらはwhere句の制約の values です。パラメーター・バインディングは SQL インジェクションからの保護を提供します。

select method は常に結果のarrayを返します。 array 内の各結果は、 database からのレコードを表す PHP のstdClass object になります。

use Illuminate\Support\Facades\DB;

$users = DB::select('select * from users');

foreach ($users as $user) {
    echo $user->name;
}

Scalar Values の選択

時々、あなたの database query は single 、 scalar value を結果として生じるかもしれません。レコードの object からクエリの scalar 結果を取得するために required とされる代わりに、 Laravel はあなたがこのscalar method を使って value を直接取得することを許可します:

$burgers = DB::scalar(
    "select count(case when food = 'burger' then 1 end) as burgers from menu"
);

複数の結果セットの選択

もし、あなたの application が複数の結果セットを返すストアドプロシージャを呼び出す場合、selectResultSets method を使用して、ストアドプロシージャによって返されるすべての結果セットを取得することができます:

[$options, $notifications] = DB::selectResultSets(
    "CALL get_user_options_and_notifications(?)", $request->user()->id
);

名前付きバインディングの使用

パラメータバインディングを表すために?を使用する代わりに、名前付きバインディングを使用して query を実行することができます:

$results = DB::select('select * from users where id = :id', ['id' => 1]);

Insert Statement の実行

insertの statement を実行するには、DB facade 上でinsertの method を使用することができます。selectと同様に、この method は SQL の query を第一引数とし、バインディングを第二引数として受け入れます。

use Illuminate\Support\Facades\DB;

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Marc']);

Update Statement の実行

updateの method は、database 内の既存のレコードをアップデートするために使用されるべきです。statement によって影響を受ける行の数は、method によって返されます。

use Illuminate\Support\Facades\DB;

$affected = DB::update(
    'update users set votes = 100 where name = ?',
    ['Anita']
);

Delete Statement の実行

delete method は、database からレコードを削除するために使用するべきです。updateと同様に、影響を受ける行の数は method によって返されます:

use Illuminate\Support\Facades\DB;

$deleted = DB::delete('delete from users');

一般的な Statement の実行

一部の database ステートメントは何も value を返さない可能性があります。この種の操作の場合、DB facade 上のstatement method を使用することができます:

DB::statement('drop table users');

準備されていない Statement の実行

時には何の values もバインドせずに SQL の statement を実行したい場合があるかもしれません。そのような場合は、DBファサードのunprepared method を用いることで実現できます。

DB::unprepared('update users set votes = 100 where name = "Dries"');

WARNING

未準備のステートメントではパラメータがバインドされないため、SQL インジェクションに対して脆弱になる可能性があります。決して user が制御する values を未準備の statement 内に許可してはなりません。

暗黙的なコミット

DB facade の statement および unprepared methods を transaction 内で使用する際には、暗黙のコミット を引き起こす statement を避ける必要があります。これらの statement は、database エンジンが間接的に全体の transaction をコミットし、Laravel が database の transaction レベルを認識できなくなります。statement の例としては、database テーブルの作成があります:

DB::unprepared('create table a (col varchar(1) null)');

すべてのステートメントのリスト が含まれている MySQL マニュアルを参照してください。これらのステートメントは暗黙のコミットをトリガーします。

複数の Database 接続を使用する

もし、application がconfig/database.phpの設定ファイルで複数の接続を定義している場合、DBの facade が提供するconnection method を通じて、各々の接続にアクセスすることができます。connection method に渡される接続名は、config/database.phpの設定ファイルにリストされている接続の一つか、confighelper を使用して実行時に設定されたものに対応しているべきです。

use Illuminate\Support\Facades\DB;

$users = DB::connection('sqlite')->select(/* ... */);

connection のインスタンスでgetPdomethod を使用して、生の、基礎となる PDO インスタンスにアクセスすることができます。

$pdo = DB::connection()->getPdo();

Query Events のリスニング

あなたの application によって実行されたすべての SQL の query に対して呼び出されるクロージャを指定したい場合は、DBファサードのlisten method を使用することができます。この method は、 logging のクエリや debugging に便利です。あなたは自分の query リスナークロージャを、service providerboot method で register することができます。

<?php

namespace App\Providers;

use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        DB::listen(function (QueryExecuted $query) {
            // $query->sql;
            // $query->bindings;
            // $query->time;
        });
    }
}

累積 Query 時間の監視

現代の webapplications の一般的なパフォーマンスのボトルネックは、database の query にかかる時間です。ありがたいことに、Laravel は、database への query 時間が single request の間に過ぎてしまったときに、あなたの選んだクロージャまたはコールバックを実行することができます。始めるには、query の時間閾 values(ミリ秒)とクロージャをwhenQueryingForLongerThanmethod に提供します。あなたはこの method を service providerboot method で呼び出すことができます。

<?php

namespace App\Providers;

use Illuminate\Database\Connection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Events\QueryExecuted;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        DB::whenQueryingForLongerThan(500, function (Connection $connection, QueryExecuted $event) {
            // Notify development team...
        });
    }
}

Database Transactions

DB facade によって提供されるtransaction method を使用すると、一連の操作を database transaction 内で実行することができます。 transaction クロージャ内で例外が throw された場合、 transaction は自動的にロールバックされ、例外は再 throw されます。クロージャが正常に実行された場合、 transaction は自動的にコミットされます。transaction method を使用する際に、手動でロールバックやコミットをする心配は必要ありません。

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
});

デッドロックの処理

transactionの method は、デッドロックが発生したときに transaction を再試行する回数を定義する任意の第二引数を受け入れます。これらの試行が全て失敗した場合、例外がスローされます:

use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');

    DB::delete('delete from posts');
}, 5);

手動で Transactions を使用する

ロールバックとコミットに完全にコントロールを持つために、手動で transaction を開始したい場合は、DB facade が提供するbeginTransaction method を使用することができます:

use Illuminate\Support\Facades\DB;

DB::beginTransaction();

rollBack method を通じて transaction を rollback することができます:

DB::rollBack();

最後に、commit method を使用して transaction をコミットすることができます:

DB::commit();

NOTE

DB ファサードの transaction メソッドは、query builderEloquent ORMの両方の transactions を制御します。

Connecting to the Database CLI

データベースの CLI に接続したい場合は、db Artisan command を使用することができます:

php artisan db

必要に応じて、 default connection ではない database connection に接続するための database connection 名を指定することができます。

php artisan db mysql

Inspecting Your Databases

db:showdb:tableの Artisan コマンドを使用すると、 database とそれに関連するテーブルについて貴重な洞察を得ることができます。 database の概要、そのサイズ、 type 、開いている接続の数、テーブルの概要を見るには、db:showの command を使用できます。

php artisan db:show

--databaseoption を使用して command に database 接続名を指定することで、どの database 接続を検査するかを指定できます。

php artisan db:show --database=pgsql

command の output 内にテーブル行のカウントと database view の詳細を含めたい場合は、それぞれ--counts--views options を提供できます。大規模な database では、行のカウントと view の詳細の取得が遅くなる可能性があります。

php artisan db:show --counts --views

また、以下の Schema も数ある database を検査するために使用することができます:

use Illuminate\Support\Facades\Schema;

$tables = Schema::getTables();
$views = Schema::getViews();
$columns = Schema::getColumns('users');
$indexes = Schema::getIndexes('users');
$foreignKeys = Schema::getForeignKeys('users');

あなたのアプリケーションの default connection ではない database connection を検査したい場合は、connection method を使用することができます。

$columns = Schema::connection('sqlite')->getColumns('users');

表の概要

あなたの database 内の個々のテーブルの概要を得たい場合は、db:table Artisan command を実行することができます。 この command は、 database テーブルの一般的な概要を提供します。これには、そのカラム、タイプ、 attributes 、 keys 、およびインデックスが含まれます:

php artisan db:table users

Monitoring Your Databases

db:monitorの Artisan command を使用すると、 Laravel に対して、 database が指定された数以上のオープン接続を管理している場合にIlluminate\Database\Events\DatabaseBusyの event を dispatch するように指示することができます。

始めるには、db:monitor command を毎分実行するように schedule する必要があります。この command は、監視したい database connection の設定名と、 event をディスパッチする前に許容すべき最大の開放接続数を受け入れます。

php artisan db:monitor --databases=mysql,pgsql --max=100

この command だけをスケジューリングするだけでは、オープンしている connection の数を知らせる notification をトリガーするのに十分ではありません。 command がオープンしている connection の数があなたのしきい values を超える database に遭遇した場合、 DatabaseBusy event が発行されます。 あなた自身または development チームに notification を送るために、application 内の AppServiceProvider でこの event を待ち受けるべきです。

use App\Notifications\DatabaseApproachingMaxConnections;
use Illuminate\Database\Events\DatabaseBusy;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Notification;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Event::listen(function (DatabaseBusy $event) {
        Notification::route('mail', 'dev@example.com')
                ->notify(new DatabaseApproachingMaxConnections(
                    $event->connectionName,
                    $event->connections
                ));
    });
}

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use