ホームページ >PHPフレームワーク >Laravel >Laravel Eloquent のための重要な実践的なヒント

Laravel Eloquent のための重要な実践的なヒント

藏色散人
藏色散人転載
2019-12-23 17:41:582543ブラウズ

Laravel Eloquent に必要な実践スキル

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 を実行してください。」などの使用を実行します。

例 1 -- findOrFail():

次のコードの実装を置き換えるには:

$user = User::find($id);
if (!$user) { abort (404); }

次のように記述できます:

$user = User::findOrFail($id);

Example 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 を追加することもできます。

たとえば、特定のタイプのユーザーを関連付け、電子メール フィールドを使用して同時に並べ替える場合は、次のようにすることができます。 ##

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; // 设置不需要维护时间字段

他にもあります。興味深い機能をいくつか列挙しただけです。詳細については、ドキュメントの抽象モデル クラスを参照してください。

6. ID による複数のレコードのクエリ

find() メソッドは誰でも知っていますよね。

$user = User::find(1);

このメソッドがパラメータとして複数の ID の配列を受け入れることができることを知っている人がほとんどいないことに非常に驚きました:

$users = User::find([1,2,3]);

7.どこX

これを行うためのエレガントな方法がありますコードの種類:

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

この種類のコードに変換します:

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

はい、正しく読みました。フィールド名をサフィックスとして使用し、その後の場所に追加すると、実行されます。魔法の方法で。

さらに、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. BelongsTo デフォルト モデル

If Thereは Author モデルにアタッチされた Post モデルであり、次のコードを Blade テンプレートに記述することができます:

{{ $post->author->name }}

しかし、著者が削除されているか、何らかの理由で設定されていない場合はどうなるでしょうか。 「存在しないオブジェクトのプロパティ」のようなエラー メッセージが表示されます。

まあ、次のように回避できます:

{{ $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() を常に名前フィールドで並べ替えたい場合はどうすればよいでしょうか?グローバル スコープを割り当てることができます。上で説明した 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. コピー: 行をコピーします

非常に簡単です。説明はあまり詳しくありませんが、データベース エンティティ (データの一部) をコピーする最良の方法は次のとおりです:

$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。モデルの作成時に追加します。操作

このアーティザン コマンドは誰もが知っています:

php artisan make:model Company

しかし、モデル関連ファイルの生成に使用できる非常に便利な識別子が 3 つあることはご存知でしょう

php artisan make:model Company -mcr

-m Create移行ファイル

-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]);

这样,我们成功在 save 时指定了 updated_at 的值。

18. update() 的结果是什么?

你是否想知道这段代码实际上返回什么?

$result = $products->whereNull('category_id')->update(['category_id' => 2]);

我是说,更新操作是在数据库中执行的,但 $result 会包含什么?

答案是受影响的行。 因此如果你想检查多少行受影响, 你不需要额外调用其他任何内容 -- update() 方法会给你返回此数字。

19. 把括号转换成 Eloquent 查询

如果你有个 and 和 or 混合的 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]);

更多laravel框架相关技术文章,请访问laravel教程栏目!

以上がLaravel Eloquent のための重要な実践的なヒントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はruoxiaozh.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。