Help us understand the problem. What is going on with this article?

Eloquent をおさらい

More than 1 year has passed since last update.

Laravelでデータベースの操作を直感的に行えるEloquent。
断片的にしか理解していなかったので、基礎的なところからドキュメントをよく読んでおさらいしてみることにしました。

注意点

EloquentORMについて始める前に、データベース接続の設定を先にしてください。

1. Eloquentの基本

  • Eloquentはデフォルトで app ディレクトリに置かれている
    • composer.json を元に auto-load できるのであればどこにおいてもOK
  • 全てのEloquentモデルは Illuminate\Database\Eloquent\Model を継承する

作成方法

php artisan make:model User

一緒にマイグレーションファイルも作る場合は、 --migration-m オプションをつける

php artisan make:model User --migration
php artisan make:model User -m

サンプル

flights テーブルに紐づくモデル Flight.php を作るとする。

Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    //
}

テーブルとの紐付け

$tableプロパティでモデルとテーブルを紐づける。

Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'my_flights';
}

主キー

Eloquent にデフォルトで設定されている主キー(Primary Key)は id

主キーを変更する:$primaryKey

id を無効にして、他のものを主キーとして設定できる。

インクリメントを無効にする:$incrementing

false にすると、インクリメントを無効にできる。

タイムスタンプ

Eloquent はデフォルトだと自動的に created_atupdated_at を各テーブルに記録する。

無効にする:$timestamps

false にすると、勝手にタイムスタンプがつかないようにできる。

フォーマットを変える:$dateFormat

http://php.net/manual/ja/function.date.php なんかを参考に。

Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

カラム名を変更: CREATED_AT UPDATED_AT

モデル内で定数を設定する。

Flight.php
<?php

class Flight extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'last_update';
}

データベース接続

基本的には .env で設定したDBに接続されるが、 $connection プロパティを使えば一部他のDBに接続が可能。

Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * The connection name for the model.
     *
     * @var string
     */
    protected $connection = 'connection-name';
}

2. データを取得してみる

Eloquentは強力なクエリビルダとして使える。

全件を取得する

<?php

use App\Flight;

$flights = App\Flight::all();

foreach ($flights as $flight) {
    echo $flight->name;
}

いろいろ制約するとき

クエリビルダとしていろんな制約をするときは、最後に get メソッドで結果を取得する。

$flights = App\Flight::where('active', 1)
               ->orderBy('name', 'desc')
               ->take(10)
               ->get();

Collectionクラスを使う

Eloquent はallget以外にも色んな形で結果を返すことができ、それらはIlluminate\Database\Eloquent\Collection インスタンスとして返ってくる。

要らないものを排除して結果を返す:reject

$collection = collect([1, 2, 3, 4]);

$filtered = $collection->reject(function ($value, $key) {
    return $value > 2;
});

$filtered->all();

// [1, 2]

ちなみにその逆は filter メソッド。

分割して結果を返す: chunk

$collection = collect([1, 2, 3, 4, 5, 6, 7]);

$chunks = $collection->chunk(4);

$chunks->toArray();

// [[1, 2, 3, 4], [5, 6, 7]]

その他のCollectionクラス

https://laravel.com/docs/5.4/eloquent-collections#available-methods

単一レコードだけ取得する

主キーを使う:find

$flight = App\Flight::find(1);

find メソッドは、複数レコードを指定して取得も可能

$flights = App\Flight::find([1, 2, 3]);

他のキーを使う:first

$flight = App\Flight::where('active', 1)->first();

例外処理:findOrFail firstOrFail

この2つのメソッドを使うと、結果が返ってこなかった時に Illuminate\Database\Eloquent\ModelNotFoundException が投げられます。
Exception をキャッチされなければ 404 が自動的に返される。

$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();

「数」を返す:count sum max

モデルインスタンスではなく「数」に関する結果だけが欲しい時につかえる。

$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');

3. データを登録・更新してみる

登録してみる

  • インスタンスを new する
  • 属性を set する
  • save する
<?php

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller
{
    /**
     * Create a new flight instance.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        // Validate the request...

        $flight = new Flight;

        $flight->name = $request->name;

        $flight->save();
    }
}

更新してみる

  • 登録とほぼ同じ手順
    • モデルを取ってくる
    • 属性を set する
    • save する
$flight = App\Flight::find(1);

$flight->name = 'New Flight Name';

$flight->save();

複数いっぺんに更新:update

更新するカラム名と値は配列にする。

App\Flight::where('active', 1)
          ->where('destination', 'San Diego')
          ->update(['delayed' => 1]);

データが勝手に書き込まれるのを防ぐ:fillable guarded

別記事でまとめてます。

http://qiita.com/shosho/items/e44974563012f0bd0a61#massassignmentexception

他のメソッド

なければ作って登録する:firstOrCreate

DBに与えられたカラムと値が存在していなかったら、DBに挿入される。

$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

$flight = App\Flight::firstOrCreate(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

なければインスタンスを作る:firstOrNew

firstOrCreate と似ているが、なければ与えられた属性を set してインスタンスが作成される。
手動で save を呼びだす必要があるので注意。

$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

$flight = App\Flight::firstOrNew(
    ['name' => 'Flight 10'], ['delayed' => 1]
);

あれば更新して、なければ登録する:updateOrCreate

$flight = App\Flight::updateOrCreate(
    ['departure' => 'Oakland', 'destination' => 'San Diego'],
    ['price' => 99]
);

4. データを削除する

  • 消したいものデータを取得
  • delete する
$flight = App\Flight::find(1);
$flight->delete();

主キーを使って削除

App\Flight::destroy(1);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(1, 2, 3);

クエリーで削除

$deletedRows = App\Flight::where('active', 0)->delete();

論理削除

実際のデータは削除せず「削除したことにして」、この場合は deleted_at に削除した日時が入る。

1. トレイト、$datesプロパティの実装

Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;

    /**
     * The attributes that should be mutated to dates.
     *
     * @var array
     */
    protected $dates = ['deleted_at'];
}

2. テーブルにdeleted_atカラムを追加する

3. メソッドを呼び出す

Schema::table('flights', function ($table) {
    $table->softDeletes();
});

論理削除したデータを抽出

if ($flight->trashed()) {
    //
}

感想

  • 削除の「Querying Soft Deleted Models」以降は目を通せなかった
    • Getting Started であっても知らないことはいっぱい
  • 「Eloquentにあるなんか便利なやつ」がCollectionクラスだと認識できた
    • Collection クラスについてもおさらいしたい
  • Eloquentを使うときにはクエリビルダを多用することがわかった
    • クエリビルダについてもおさらいしたい

参考

https://laravel.com/docs/5.4/eloquent

shosho
Qiitaには忘れそうなこと、勉強したことをメモしてます。
https://shosho-egg.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away