ホームページ >バックエンド開発 >PHPチュートリアル >Laravel 5.1 ドキュメント戦略 -- Laravel Eloquent ORM の最も強力だが理解が難しい部分: データ関係

Laravel 5.1 ドキュメント戦略 -- Laravel Eloquent ORM の最も強力だが理解が難しい部分: データ関係

WBOY
WBOYオリジナル
2016-06-20 12:33:411158ブラウズ

はじめに

実際、Eloquent ORM はテーブル操作をデータ モデル操作に置き換えることができることを誰もが知っています。そのため、テーブルの関連クエリは Eloquent にあります。これは、モデル間の関連付けクエリです。これがこの章の主要な内容です。

Eloquent は、次の 6 種類のテーブル間リレーションシップをサポートします。

  • One To One (1 対 1) )

  • 1 対多

  • 多対多

  • Has Many Through (テーブル間で 1 対多)

  • 多態性関係 (belongsTo 多態性)

  • 多対多多態性関係 (belongsToMany 多態性) )

最初の 3 つの関係が何であるかについては説明しません (Baid 自身で理解してください) これには、多くの忍耐とオブジェクト思考に慣れる努力が必要です。とりあえずは SQL ですが、しばらく練習すればとても簡単に使えることがわかります。

もちろん、Eloquent は強力すぎるため、毎回多くのものがロードされると不満を言う人もいます。これは効率に影響します (実際には影響はありませんので、納得できない場合は取得してください。データが教えてくれました) が、コード作成効率、可読性、保守性の点で質的な飛躍であると言えるので、それを優先することを強くお勧めします。

私はこの章を最初に学びましたが、チュートリアルを書いたのは最後でした。幸いなことに、私は製品の出身なので、複雑なことを明確に説明できるはずです。地球上で最も強力な ORM を理解しましょう: Eloquent

基本概念

まずその使用方法を見てみましょう:

$user->posts()->where('active', 1)->get();

使用方法は次のとおりです。 $user オブジェクトは、彼が合計で公開した記事の数を調べます (ステータスは公開済み)。

ここでは、posts() が $user のメソッドであることがわかります。そのため、関連するクエリを使用するには、まず $user モデルで関係 (メソッド) を定義する必要があります。 -one

この図から、Eloquent モデル リレーションシップを使用するには、最初のステップでモデル内でモデル リレーションシップを定義し、2 番目のステップで正しいモデル リレーションシップを準備することがわかります。 3 番目の部分では、クエリ メソッドのバインディングとアンバインド メソッドを使用します。このプロセスに従って、次のモデルの関係を理解し​​て説明します。絵を繰り返し観察してください!

モデルの定義

ユーザー モデルの定義

電話モデルの定義

namespace App;use Illuminate\Database\Eloquent\Model;class User extends Model{        public function phone()    {        return $this->hasOne('App\Phone');    }}
注: モデルを定義するときは、単数形に注意してください混乱を避けるために、メソッド名には単数形を使用し、「1 つ」には単数形を使用し、「多数」には複数形を使用します。 hasOne() などのリレーションシップ バインディング メソッドは数多くありますが、徐々に慣れて、使用中に注意する必要があります。

データ テーブル
namespace App;use Illuminate\Database\Eloquent\Model;class Phone extends Model{    public function user()    {        return $this->belongsTo('App\User');    }}

主に注意すべき点は、この例には外部キーと中間テーブルが含まれていないことです。

リレーションシップ クエリ

モデル リレーションシップ メソッド。クエリ

これはモデル メソッド クエリで、ここにある $user->posts() は DQB オブジェクトであり、その後にさまざまなデータベース クエリ メソッドが続きます。 query

$user->posts()->where('active', 1)->get();
リレーションシップを属性として使用して、コレクションを直接検索できますが、欠点は、DQB メソッドを続行できないことです。

これら 2 つのメソッドは非常に一般的に使用されるため、適切に使用する必要があります (以下同様、説明は省略します)

関係のバインディングとリリース
$user->posts;

共通のバインディングメソッドは save( ; リレーションシップ モデル内;

1 対多

バック バインディング

belongsTo 関係を通じてバインドする場合図に示すように、associate() を使用して Determine をバインドし、最後に save() を実行できます。

多対多

オブジェクト ID がここに入力され、配列形式でバッチでバインドできることに注意してください。

save() メソッドはそのままです。リレーションシップ バインディングに適用可能;

中間テーブルの操作

多対多のリレーションシップには追加の中間テーブルがあるため、Eloquent はデフォルトでその中の外部キーを操作できるだけでなく、中間テーブルの他のフィールドも操作できます。例を参照してください。

sync() メソッド

sync は同期です。中間テーブルは sync() で同じパラメータに同期され、パラメータに書き込まれていないパラメータは移動されるため、

Has Many Through (クロステーブル 1) に使用できます。 -to-many)

実際には、これは単なる簡単なクエリ方法です。図を見てください。本来は、まず国からユーザーを確認し、次にユーザーから今すぐ投稿を確認することができます。 Country を介して Post を直接確認できます。
App\User::find(1)->roles()->save($role, ['expires' => $expires]);
$user->roles()->attach($roleId, ['expires' => $expires]);
通常、 Country と User、User と Post テーブルの間の関係は事前に確立されています。このとき、hasManyThrough;
$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);
$user->roles()->sync([1 => ['expires' => true], 2, 3]);
多態性関係 (ポリモーフィズムに属します)

本来belongsTo只能属于一种对象的,就像女朋友只能属于男朋友;现在好了,女朋友不仅可以属于男朋友,还可以属于干爹了。

开玩笑的,最常见的应用还是图片,可以属于多种模型,看图;

我们发现这里的动词变成了morphTo(), morphMany();

先上一小段英语课,提升一下语感:

morph这个词的意思是改变形态,简称变态;这个和变形金刚的那个transform是不一样的,那个主要是改变形状;

morphTo(), morphMany(); 其实就是belongsTo() 和 hasMany() 多态形式,多态就是不仅拥有男票,还有干爹,有点“变态”;

关于绑定和解绑

associate()不适用用于morphTo();所以只能单向的用save()绑定了;

关于解绑,dissociate()也不适用用于morphTo();所以,只能把Photo实例删除!!删除了就没任何关系了(因为没有中间表)

感觉有点不是很自然的设计,不过目前调查下来情况就是这样;

Many To Many Polymorphic Relations(belongsToMany多态)

这个最典型的应用就是标签了,标签要涉及多对多的关系,还涉及对应不同类型的模型的问题,所以就是belongsToMany+多态;

看图,可绑定,可解绑;

Eager Loading(预加载)

这个问题很简单,看个实例你就懂了:

$books = App\Book::all();foreach ($books as $book) {    echo $book->author->name;}

万一books有一万本,那么循环就要1万次,每次循环,因为用了关联查询 $book->author->name; ,都会读数据库一次,意味着至少读数据库一万次,数据库哭了。

Eager Loading 就是让数据库读取发生在循环之前:

$books = App\Book::with('author')->get();foreach ($books as $book) {    echo $book->author->name;}

看,加了个神奇的with()后,所有数据在foreach前都读出来了,后面循环的只是读出来的数据,一共查询数据库2次!!

Eager Loading可以极大的缓解数据库查询压力,是性能优化的重要手段!

Eager Loading 多个关系

就是一次多加几张关联表而已;

$books = App\Book::with('author', 'publisher')->get();

嵌套 Eager Loading

$books = App\Book::with('author.contacts')->get();

把书的作者读出来,顺便把作者的联系方式读出来。

有条件的 Eager Loading

上面说的是整张表整张表的读出来,太土豪了,其实有时候我们只需要表里的部分记录:

$users = App\User::with(['posts' => function ($query) {    $query->where('title', 'like', '%first%');}])->get();

这中闭包的写法我们讲过多次,就是加个条件而已;

Lazy Eager Loading

这标题难道不是自相矛盾吗?又Lazy,又Eager?

哦,原来是在lazy的流程里判断需不需要eager loading一下:

$books = App\Book::all();if ($someCondition) {    $books->load('author', 'publisher');}
$books->load(['author' => function ($query) {    $query->orderBy('published_date', 'asc');}]);

注意这个load(),这是对collection用的;

跨模型更新时间戳

简单的来说,就是一条评论更新的时候,顺便把文章的'updated_at'字段也更新了;

namespace App;use Illuminate\Database\Eloquent\Model;class Comment extends Model{    /**     * All of the relationships to be touched.     *     * @var array     */    protected $touches = ['post'];    /**     * Get the post that the comment belongs to.     */    public function post()    {        return $this->belongsTo('App\Post');    }}

设置$touches这个属性;

然后你更新Comment的时候,就会把Post的'updated_at'字段也更新了;

更多内容请访问: Laravel 5.1 文档攻略

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。