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

いつか使える(かもしれない) Laravel Tips

TL;DR

VALU Advent Calendar 2019の7日目の記事です。
今回はいつか使えるであろうLaravelの知見を列挙してみました。

モデルとマイグレーションファイルとresourceのあるコントローラーを同時に生成する

いつも新しいファイルの生成時に使うそれぞれのコマンドたち

$ php artisan make:migration create_posts_table

$ php artisan make:model Post

$ php artisan make:controller Post

実はこれらは1つのコマンド実行できる

$ php artisan make:model Post -mcr

m : モデル
c : コントローラー
r : resource

新しい機能を作る時などに試して欲しい

マイグレーションと同時にSeedingする

新しいマイグレーションファイルを作った時、ダミーデータでテストしたくなるのが常でしょう
しかし、dev環境などだとわざわざサーバーにssh接続してコマンドを打つのは面倒
そんな時、下記のようにマイグレーションファイルに追記すると、Seedingもできるようになります

public function up()
{
    Schema::create('themes', function (Blueprint $table) {
        $table->increments('id');
        $table->text('name');
    });

    Artisan::call('db:seed', [
        '--class' => ThemesTableSeeder::class
    ]);
}

productionでは動かないようにするのも忘れずに

public function up()
{
    Schema::create('themes', function (Blueprint $table) {
        $table->increments('id');
        $table->text('name');
    });

    if (app()->environment() != 'production') {
        Artisan::call('db:seed', [
            '--class' => ThemesTableSeeder::class
        ]);
    }
}

whereメソッドのTips

$users = User::where('approved', 1)->get();

whereメソッドはカラム名とつなげることもできます

$users = User::whereApproved(1)->get();

リレーションにおけるN+1問題の解決

親レコードのものをこのようにforeach文などで回して表示したい場合があるとします

index.blade.php
@foreach ($sessions as $session)
<tr>
  <td>{{ $session->created_at }}</td>
  <td>{{ $session->user->name }}</td>
</tr>
@endforeach

リレーション内容

Session.php
public function user()
{
    return $this->belongsTo(User::class);
}

その時の間違ったコントローラーの書き方

public function index()
{
    $sessions = Session::all();
    return view('sessions.index', compact('sessions');
}

これだとSessionモデルのインスタンスを取得した後、ループが回るたびにUserモデルのインスタンスを取得してしまい、表示数によっては負荷の大きい処理になってしまいます
そうならないための正しいコントローラーの書き方が以下になります

public function index()
{
    $sessions = Session::with('user')->get();
    return view('sessions.index', compact('sessions');
}

withメソッドで事前にリレーション先のモデルのインスタンスを取得しておけば、ループで回したとしてもすでに取得したインスタンスを使うだけなので、処理がとても軽くなります
いわゆるEagerロードというやつですね

リレーション先が空の場合の表示

ユーザーネームがない匿名ユーザーなどの処理に使えます
bladeで処理する場合

{{ $payment->user->name ?? 'Anonymous' }}

それより前にEloquentで処理する場合

public function user()
{
    return $this->belongsTo(User::class)
      ->withDefault(['name' => 'Anonymous']);
}
{{ $payment->user->name }}

簡略化したAuth::user()->id

ログイン中のユーザーIDが欲しい時にいつも使うであろうAuth::user()->id
しかし、こういう短い書き方もできます

Auth::id()

id以外のプロパティも指定でき、ログアウト中はnullになります

参考

Laravel Daily

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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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