Laravel5.5 LTS 日本語ドキュメント

このリポジトリはPHP Webアプリフレームワークである、LaravelのLTSバージョンである5.5の公式英文ドキュメントを日本語へ翻訳しています。

This project is maintained by okinaka

データベース:利用開始

イントロダクション

LaravelはSQLを直接使用する場合でも、FluentクエリビルダEloquent ORMを使う時でも、データベースの取り扱いをとても簡単にしてくれます。現在、Laravelは以下のデータベースシステムを使用しています。

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server

設定

データベース設定ファイルはconfig/database.phpです。このファイルで使用するデータベース接続を全部定義すると同時に、デフォルトで使用する接続も指定してください。サポートしているほとんどのデータベースシステムの例がファイルの中に用意しています。

デフォルトでLaravelのサンプル環境設定は、ローカルマシン上でLaravelでの開発を行うのに便利な仮想マシンであるLaravel Homestead用に設定してあります。もちろん、ローカルのデータベースに合わせるため、自由に変更してくだい。

SQLite設定

touch database/database.sqliteなどのコマンドを使い、新しいSQLiteデータベースを作成した後、この新しいデータベースの絶対パスを環境変数へ設定します。

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

Read/Write接続

SELECT文に別のデータベース接続を利用したい場合もあると思います。INSERT、UPDATE、DELETE文では他の接続に切り替えたい場合などです。Laravelでこれを簡単に実現できます。SQLをそのまま使う場合であろうと、クエリビルダやEloquent ORMを利用する場合であろうと、適切な接続が利用されます。

Read/Write接続を理解してもらうため、以下の例をご覧ください。

'mysql' => [
    'read' => [
        'host' => '192.168.1.1',
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'sticky'    => true,
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

設定配列にreadwritesticky、3つのキーが追加されたことに注目して下さい。2つのキーともhostというキーを一つ持っています。readwrite接続時の残りのデータベースオプションは、メインのmysql配列からマージされます。

readwriteの配列には、メインの配列の値をオーバーライドしたいものだけ指定してください。この場合、192.168.1.1は”read”接続に利用され、一方192.168.1.2が”write”接続に利用されます。メインのmysql配列に含まれる、データベース接続情報、プレフィックス、文字セットなどその他のオプションは、両方の接続で共有されます。

stickyオプション

stickyオプションはオプショナル値で、現在のリクエストサイクル中にデータベースへ書き込まれたレコードを即時に読み込めるようにします。stickyオプションが有効で、現在のリクエストサイクル中にデータベースに対して「書き込み(write)」処理が実行されると、すべての「読み込み(read)」操作で”write”接続が使われるようになります。これによりリクエストサイクル中に書き込まれたデータが、同じリクエスト中にデータベースから即時に読み込まれることが確実になります。

複数接続の使用

複数の接続を使用する場合は、DBファサードのconnectionメソッドを利用し、各接続にアクセスできます。connectionメソッドに渡す「名前」は、config/database.php設定ファイルの中のconnectionsにリストされている名前を指定します。

$users = DB::connection('foo')->select(...);

裏で動作しているPDOインスタンスに直接アクセスしたい場合は、接続インスタンスにgetPdoメソッドを使います。

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

SQLクエリの実行

データベース接続の設定を済ませれば、DBファサードを使用しクエリを実行できます。DBファサードは selectupdateinsertdeletestatementのクエリタイプごとにメソッドを用意しています。

SELECTクエリの実行

基本的なクエリを行うには、DBファサードのselectメソッドを使います。

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * アプリケーションの全ユーザーリストを表示
     *
     * @return Response
     */
    public function index()
    {
        $users = DB::select('select * from users where active = ?', [1]);

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

selectメソッドの最初の引数はSQLクエリで、2つ目の引数はクエリに結合する必要のあるパラメーターです。通常、パラメーターはwhere節制約の値です。パラメーター結合はSQLインジェクションを防ぐために提供されています。

selectメソッドはいつも結果の「配列」を返します。結果の値へアクセスできるように、配列に含まれる結果はそれぞれ、PHPのStdClassオブジェクトになります。

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

名前付き結合の使用

パラメーター結合に?を使う代わりに名前付きの結合でクエリを実行できます。

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

INSERT文の実行

insert文を実行するには、DBファサードのinsertメソッドを使います。selectと同様に、このメソッドは第1引数にSQLクエリそのもの、第2引数に結合を取ります。

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

UPDATE文の実行

データベースの既存レコードの更新には、updateメソッドを使います。このメソッドの返却値は影響を受けたレコード数です。

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

DELETE文の実行

データベースからレコードを削除するには、deleteメソッドを使います。updateと同様に、削除したレコード数が返されます。

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

通常のSQL文を実行する

いつくかのデータベース文は値を返しません。こうしたタイプの操作には、DBファサードのstatementメソッドを使います。

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

クエリイベントのリッスン

アプリケーションで実行される各SQLクエリを取得したい場合は、listenメソッドがし良いうできます。このメソッドはクエリをログしたり、デバッグしたりするときに便利です。クエリリスナはサービスプロバイダの中で登録します。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * アプリケーションサービスの初期処理
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * サービスプロバイダの登録
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

データベーストランザクション

一連の操作をデータベーストランザクション内で実行するには、DBファサードのtransactionメソッドを使用してください。トランザクション「クロージャ」の中で例外が投げられると、トランザクションは自動的にロールバックされます。「クロージャ」が正しく実行されると、自動的にコミットされます。transactionメソッドを使用すれば、ロールバックやコミットを自分でコードする必要はありません。

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
});

デッドロックの処理

transactionメソッドは第2引数に、デッドロック発生時のトランザクション再試行回数を指定できます。試行回数を過ぎたら、例外が投げられます。

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
}, 5);

手動トランザクション

トランザクションを自分で開始し、ロールバックとコミットを完全にコントロールしたい場合は、DBファサードのbeginTransactionメソッドを使います。

DB::beginTransaction();

rollBackメソッドにより、トランザクションをロールバックできます。

DB::rollBack();

同様に、commitメソッドにより、トランザクションをコミットできます。

DB::commit();

{tip} DBファサードのトランザクションメソッドは、クエリビルダEloquent ORMのトランザクションを両方共にコントロールします。