20個のLaravel Eloquentに必要な実用的なテクニック


Eloquent ORMは簡単なメカニズムのように見えますが、下位層では、多くの半隠し関数とあまり知られていない方法でより多くの機能を実現しています.この文章では、いくつかの小さなテクニックを説明します.
1.増減
次の代わりに実装します.
$article = Article::find($article_id);
$article->read_count++;
$article->save();

このようにすることができます.
$article = Article::find($article_id);
$article->increment('read_count');

以下の方法も実現できます.
Article::find($article_id)->increment('read_count');
Article::find($article_id)->increment('read_count', 10); // +10
Product::find($produce_id)->decrement('stock'); // -1
  • *




  • 2.まずXメソッドを実行し、Xメソッドの実行が成功しなければYメソッドを実行する
    Eloquentには、2つのメソッドを組み合わせて使用できる関数がかなりあります.たとえば、「Xメソッドを先に実行してください.Xメソッドの実行が成功しなければYメソッドを実行します」などです.
    例1-findOrFail():
    次のコードの実装を置き換えるには、次の手順に従います.
    $user = User::find($id);
    if (!$user) { abort (404); }
    

    次のように書くことができます.
    $user = User::findOrFail($id);
    

    例2-firstOrCreate():
    次のコードの実装を置き換えるには、次の手順に従います.
    $user = User::where('email', $email)->first();
    if (!$user) {
      User::create([
        'email' => $email
      ]);
    }
    

    これで書けます.
    $user = User::firstOrCreate(['email' => $email]);
    
  • *




  • 3.モデルのboot()メソッド
    Eloquentモデルでは、boot()という不思議な場所があります.そこで、デフォルトの動作を上書きすることができます.
    class User extends Model
    {
        public static function boot()
        {
            parent::boot();
            static::updating(function($model)
            {
                //       
                //       ,     $model->something = transform($something);
            });
        }
    }
    

    モデルオブジェクトを作成するときにいくつかのフィールドの値を設定するのは、おそらく最も人気のある例の1つです.モデルオブジェクトを作成するときにUUIDフィールドを生成する方法を見てみましょう.
    public static function boot()
    {
      parent::boot();
      self::creating(function ($model) {
        $model->uuid = (string)Uuid::generate();
      });
    }
    
  • *




  • 4.条件付きソートの関連付け
    関連関係を定義する一般的な方法:
    public function users() {
        return $this->hasMany('App\User');
    }
    

    知ってる?上記に加えてwhereまたはorderByを追加することもできますか?たとえば、emailフィールドを使用してソートしながら、特定のタイプのユーザーを関連付けたい場合は、次のようにできます.
    public function approvedUsers() {
        return $this->hasMany('App\User')->where('approved', 1)->orderBy('email');
    }
    
  • *




  • 5.モデル特性:時間、追加など
    Eloquentモデルには、クラスのプロパティ形式を使用するパラメータがあります.最も一般的なものは次のとおりです.
    class User extends Model {
        protected $table = 'users';
        protected $fillable = ['email', 'password']; //          ,  User::create()    ,     
        protected $dates = ['created_at', 'deleted_at']; //    Carbon      
        protected $appends = ['field1', 'field2']; // json   ,     
    }
    

    それだけでなく、
    protected $primaryKey = 'uuid'; //     
    public $incrementing = false; //        
    protected $perPage = 25; //           (  15)
    const CREATED_AT = 'created_at';
    const UPDATED_AT = 'updated_at'; //        
    public $timestamps = false; //            
    

    さらに、私はいくつかの興味深い特性だけをリストして、具体的にはドキュメントabstract Model classを参照してすべての特性を理解します.
  • *




  • 6.IDで複数のレコードを問い合わせるfind()の方法は誰もが知っていますよね?
    $user = User::find(1);
    

    この方法が複数のIDの配列をパラメータとして受け入れることができることを知っている人は意外に少ない.
    $users = User::find([1,2,3]);
    
  • *




  • 7. WhereX
    このコードを優雅にする方法があります.
    $users = User::where('approved', 1)->get();
    

    次のように変換します.
    $users = User::whereApproved(1)->get();
    

    はい、見間違えていません.フィールド名を接尾辞としてwhereに追加すると、マジックメソッドで実行できます.
    また、Eloquentでは時間に関する事前定義方法もあります.
    User::whereDate('created_at', date('Y-m-d'));
    User::whereDay('created_at', date('d'));
    User::whereMonth('created_at', date('m'));
    User::whereYear('created_at', date('Y'));
    
  • *




  • 8.リレーションシップによるソート
    複雑な「テクニック」です.フォーラムの話題を最新の投稿で並べ替えたいですか?フォーラムの最新更新のテーマは一番前によくあるニーズですよね?
    まず、トピックの最新の投稿に対して個別の関係を定義します.
    public function latestPost()
    {
        return $this->hasOne(\App\Post::class)->latest();
    }
    

    そして、コントローラでは、この「魔法」を実現することができます.
    $users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
    
  • *




  • 9.Eloquent::when()--if-elseを使用しない
    多くの人が「if-else」を使ってクエリー条件を書くのが好きです.
    if (request('filter_by') == 'likes') {
        $query->where('likes', '>', request('likes_amount', 0));
    }
    if (request('filter_by') == 'date') {
        $query->orderBy('created_at', request('ordering_rule', 'desc'));
    }
    

    より良い方法があります.when()を使用します.
    $query = Author::query();
    $query->when(request('filter_by') == 'likes', function ($q) {
        return $q->where('likes', '>', request('likes_amount', 0));
    });
    $query->when(request('filter_by') == 'date', function ($q) {
        return $q->orderBy('created_at', request('ordering_rule', 'desc'));
    });
    

    優雅に見えないかもしれませんが、強力な機能はパラメータを伝達することです.
    $query = User::query();
    $query->when(request('role', false), function ($q, $role) {
        return $q->where('role_id', $role);
    });
    $authors = $query->get();
    
  • *




  • 10.一対の複数がデフォルトのモデルオブジェクトを返す
    記事の作成者を表示し、テンプレートコードを次のようにする場合があります.
    {{ $post->author->name }}
    

    ただし、作成者の情報が削除された場合、または何らかの理由で設定されていない場合.コードは、「property of non-object」などのエラーを返します.
    もちろん、このように処理することができます.
    {{ $post->author->name ?? '' }}
    

    Eloquent関係でこのようにすることができます.
    public function author()
    {
        return $this->belongsTo('App\Author')->withDefault();
    }
    

    この例では、テキストに作成者の情報がない場合、author()は空のApp\Authorモデルオブジェクトを返します.
    また、デフォルトのモデルオブジェクトのプロパティにデフォルト値を割り当てることもできます.
    public function author()
    {
        return $this->belongsTo('App\Author')->withDefault([
            'name' => 'Guest Author'
        ]);
    }
    
  • *




  • 11.代入関数によるソート
    このようなコードを想像してみてください.
    function getFullNameAttribute()
    {
      return $this->attributes['first_name'] . ' ' . $this->attributes['last_name'];
    }
    

    今、「full_name」でソートしたい?効果がないことがわかりました.
    $clients = Client::orderBy('full_name')->get(); //    
    

    解決策は簡単だ.結果を取得した後、結果をソートする必要がある.
    $clients = Client::get()->sortBy('full_name'); //   !
    

    メソッド名が異なることに注意してください.orderByではなくsortByです.
  • *




  • 12.グローバル役割ドメインでのデフォルトのソートUser::all()を常にnameフィールドでソートしたい場合は?グローバルな役割ドメインを割り当てることができます.boot()という上記の方法に戻りましょう.
    protected static function boot()
    {
        parent::boot();
    
        //    name     
        static::addGlobalScope('order', function (Builder $builder) {
            $builder->orderBy('name', 'asc');
        });
    }
    

    読み取りクエリーの役割ドメインを拡張します.
  • *




  • 13.オリジナルクエリー方法
    場合によっては、Eloquent文にオリジナルクエリーを追加する必要があります.幸いなことに、確かにこのような方法があります.
    // whereRaw
    $orders = DB::table('orders')
        ->whereRaw('price > IF(state = "TX", ?, 100)', [200])
        ->get();
    
    // havingRaw
    Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get();
    
    // orderByRaw
    User::where('created_at', '>', '2016-01-01')
      ->orderByRaw('(updated_at - created_at) desc')
      ->get();
    
  • *




  • 14.コピー:1行のコピーをコピーする
    簡単です.詳細については説明しません.次に、データベース・エンティティ(1つのデータ)をコピーする最善の方法を示します.
    $task = Tasks::find(1);
    $newTask = $task->replicate();
    $newTask->save();
    
  • *




  • 15.Chunk()メソッドの大きなブロックデータ
    Eloquentとは完全に関連しておらず、Collection(コレクション)については多くのものがありますが、ビッグデータのコレクションを処理するのに役立ちます.chunk()を使用して、これらのデータを小さなデータブロックに分割することができます.
    変更前:
    $users = User::all();
    foreach ($users as $user) {
        // ...
    

    このようにすることができます.
    User::chunk(100, function ($users) {
        foreach ($users as $user) {
            // ...
        }
    });
    
  • *




  • 16.モデルの作成時に追加のものを作成する
    Artisanコマンドは知っています.
    php artisan make:model Company
    

    しかし、モデルに関連するファイルを生成できる3つの有用なタグがあることを知っていますか?
    php artisan make:model Company -mcr
    
  • -mは、移行ファイル
  • を作成します.
  • -cはコントローラ
  • を作成します.
  • -rは、コントローラがリソースコントローラであるべきであることを示す
  • .
  • *




  • 17.saveメソッドを呼び出すときupdated_を指定するat ->save()の方法でパラメータを受け入れることができることを知っていますか?入力パラメータによってデフォルトの動作をブロックできます.updated_atの値を現在のタイムスタンプに更新します.
    $product = Product::find($id);
    $product->updated_at = '2019-01-01 10:00:00';
    $product->save(['timestamps' => false]);
    

    これにより、saveupdated_atの値を指定することに成功しました.
  • *




  • 18.update()の結果は何ですか.
    このコードが実際に何を返しているか知りたいですか?
    $result = $products->whereNull('category_id')->update(['category_id' => 2]);
    

    更新操作はデータベースで実行されますが、$resultには何が含まれていますか?
    答えは影響を受ける行です.そのため、どの行が影響を受けているかを確認したい場合は、他の何も呼び出す必要はありません.update()メソッドは、この数字を返します.
  • *




  • 19.かっこをEloquentクエリに変換するandorが混在するSQLクエリーがある場合は、次のようにします.
    ... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
    

    どうやってEloquentで翻訳しますか?次は、エラーの方法です.
    $q->where('gender', 'Male');
    $q->orWhere('age', '>=', 18);
    $q->where('gender', 'Female');
    $q->orWhere('age', '>=', 65);
    

    順番が合わない.正しい開き方は少し複雑で、サブクエリとして閉パッケージを使用します.
    $q->where(function ($query) {
        $query->where('gender', 'Male')
            ->where('age', '>=', 18);
    })->orWhere(function($query) {
        $query->where('gender', 'Female')
            ->where('age', '>=', 65);
    })
    
  • *




  • 20.複素パラメータのorWhere
    やっと、orWhere()にアレイパラメータを渡すことができます.通常の方法:
    $q->where('a', 1);
    $q->orWhere('b', 2);
    $q->orWhere('c', 3);
    

    このようにすることができます.
    $q->where('a', 1);
    $q->orWhere(['b' => 2, 'c' => 3]);
    
  • *




  • もっと隠れた秘訣があると確信していますが、少なくとも上のいくつかがあなたにとって新しいことを望んでいます.
    もっと近代的なPHP知識、Laravel/PHP知識コミュニティに行ってください