這篇文章主要介紹了PHP的Laravel框架中Eloquent物件關係映射使用,重點講述了Eloquent的資料模型間關係,需要的朋友可以參考下
零、什麼是Eloquent
Eloquent 是Laravel 的'ORM',即'Object Relational Mapping',物件關係映射。 ORM 的出現是為了幫我們把資料庫的運作變得更方便。
Eloquent 讓一個 'Model類別' 對應一張資料庫表,並且在底層封裝了很多 'function',可以讓 Model 類別非常方便地呼叫。
來看一段如下程式碼:
<?php class Article extends \Eloquent { protected $fillable = []; }
'protected $fillable = [];' 這一行程式碼在這裡沒有任何價值,是generator 自動生成的,在此我們不做討論。
這個類別簡直再簡單不過了,沒有指定命名空間,沒有建構函數,如果那一行沒有意義的程式碼也不算上的話,這個檔案就只有兩個有實際意義的東西: 'Article ' 和'\Eloquent'。沒錯,Eloquent 就是這麼屌炸天,只需要繼承一下 Eloquent 類,就可以乾 'first() find() where() orderBy()' 等非常非常多的事情,這就是面向對象的強大威力。
一、Eloquent 基本用法
廢話不多說,下面我將直接展示 Eloquent 的幾種常見用法的程式碼。
找到id 為2 的文章列印其標題
$article = Article::find(2); echo $article->title;
找出標題為「我是標題」的文章,並列印id
$article = Article::where('title', '我是标题')->first(); echo $article->id;
查詢出所有文章並循環列印所有標題
$articles = Article::all(); // 此处得到的 $articles 是一个对象集合,可以在后面加上 '->toArray()' 变成多维数组。 foreach ($articles as $article) { echo $article->title; }
在10 ~20 之間的所有文章並列印所有標題
$articles = Article::where('id', '>', 10)->where('id', '<', 20)->get(); foreach ($articles as $article) { echo $article->title; }
#查詢所有文章並循環列印所有標題,按照updated_at 倒序排序
#
$articles = Article::where('id', '>', 10)->where('id', '<', 20)->orderBy('updated_at', 'desc')->get(); foreach ($articles as $article) { echo $article->title; }
基礎使用要點
1. 每一個繼承了Eloquent 的類別都有兩個'固定用法' 'Article::find($number)' 'Article: :all()',前者會得到一個帶有資料庫中取出來值的對象,後者會得到一個包含整個資料庫的物件集合。
2. 所有的中間方法如'where()' 'orderBy()' 等都能夠同時支援'靜態' 和'非靜態鍊式' 兩種方式調用,即'Article::where( )...' 和'Article::....->where()'。
3. 所有的'非固定用法' 的調用最後都需要一個操作來'收尾',本片教程中有兩個'收尾操作':'->get()' 和'- >first()'。
二、中間操作流程
Builder 這個單字可以直譯成建構器,但是「中間操作流程」比較容易理解,因為資料庫運算大部分時候都是鍊式運算的。
中間操作流,請看程式碼:
Article::where('id', '>', 10)->where('id', '<', 20)->orderBy('updated_at', 'desc')->get();
#這段程式碼的`::where()->where()- >orderBy()` 就是中間操作流程。中間操作流用物件導向的方法來理解,可以總結成一句話:
建立一個對象,並不斷修改它的屬性,最後用一個操作來觸發資料庫操作。
如何找到中間操作流的蛛絲馬跡
中間操作流這個東西,文檔裡幾乎沒有任何有價值的信息,那麼,我們該怎麼找出這個玩意兒呢?很簡單,使用以下程式碼:
$builder = Article::where('title', "我是标题")->title;
然後你就會看到下面的錯誤:
為什麼會出錯?因為 `Article::where()` 了之後依然是 `Builder` 對象,還不是 `Article` 對象,不能直接取 `title`。
「終結者」方法
所謂「終結者」 方法,指的是在N 個中間操作流程方法對某個Eloquent 物件進行加工以後,觸發最終的資料庫查詢操作,得到返回值。
`first()` `get()` `paginate()` `count()` `delete()` 是用的比較多的一些「終結者」 方法,他們會在中間操作流的最後出現,把SQL 打給資料庫,得到回傳數據,經過加工回傳一個Article 物件或是一群Article 物件的集合。
複雜用法範例
Article::where('id', '>', '100')->where('id', '<', '200')->orWhere('top', 1)->belongsToCategory()->where('category_level', '>', '1')->paginate(10);
三、模型間關係(關聯)
1.一對一關係
顧名思義,這描述的是兩個模型之間一對一的關係。這種關係是不需要中間表的。
假如我們有兩個模型:User 和Account,分別對應註冊用戶和消費者,他們是一對一的關係,那麼如果我們要使用Eloquent 提供的一對一關係方法,表結構應該是這樣的:
user: id ... ... account_id account: id ... ... user_id
假設我們需要在User 模型中查詢對應的Account 表的信息,那麼程式碼應該是這樣的。 `/app/models/User.php`:
<?php class User extends Eloquent { protected $table = 'users'; public function hasOneAccount() { return $this->hasOne('Account', 'user_id', 'id'); } }
然后,当我们需要用到这种关系的时候,该如何使用呢?如下:
$account = User::find(10)->hasOneAccount;
此时得到的 `$account` 即为 `Account` 类的一个实例。
这里最难的地方在于后面的两个 foreign_key 和 local_key 的设置,大家可以就此记住:在 User 类中,无论 hasOne 谁,第二个参数都是 `user_id`,第三个参数一般都是 `id`。由于前面的 `find(10)` 已经锁定了 id = 10,所以这段函数对应的 SQL 为: `select * from account where user_id=10`。
这段代码除了展示了一对一关系该如何使用之外,还传达了三点信息,也是我对于大家使用 Eloquent 时候的建议:
(1). 每一个 Model 中都指定表名
(2). has one account 这样的关系写成 `hasOneAccount()` 而不是简单的 `account()`
(3). 每次使用模型间关系的时候都写全参数,不要省略
相应的,如果使用 belongsTo() 关系,应该这么写:
<?php class Account extends Eloquent { protected $table = 'accounts'; public function belongsToUser() { return $this->belongsTo('User', 'user_id', 'id'); } }
2.一对多关系
学会了前面使用一对一关系的基础方法,后面的几种关系就简单多了。
我们引入一个新的Model:Pay,付款记录。表结构应该是这样的:
user: id ... ... pay: id ... ... user_id
User 和 Pay 具有一对多关系,换句话说就是一个 User 可以有多个 Pay,这样的话,只在 Pay 表中存在一个 `user_id` 字段即可。 `/app/models/User.php`:
<?php class User extends Eloquent { protected $table = 'users'; public function hasManyPays() { return $this->hasMany('Pay', 'user_id', 'id'); } }
然后,当我们需要用到这种关系的时候,该如何使用呢?如下:
$accounts = User::find(10)->hasManyPays()->get();
此时得到的 `$accounts` 即为 `Illuminate\Database\Eloquent\Collection` 类的一个实例。大家应该也已经注意到了,这里不是简单的 `-> hasOneAccount` 而是 `->hasManyPays()->get()`,为什么呢?因为这里是 `hasMany`,操作的是一个对象集合。
相应的 belongsTo() 的用法跟上面一对一关系一样:
<?php class Pay extends Eloquent { protected $table = 'pays'; public function belongsToUser() { return $this->belongsTo('User', 'user_id', 'id'); } }
3.多对多关系
多对多关系和之前的关系完全不一样,因为多对多关系可能出现很多冗余数据,用之前自带的表存不下了。
我们定义两个模型:Article 和 Tag,分别表示文章和标签,他们是多对多的关系。表结构应该是这样的:
article: id ... ... tag: id ... ... article_tag: article_id tag_id
在 Model 中使用:
<?php class Tag extends Eloquent { protected $table = 'tags'; public function belongsToManyArticle() { return $this->belongsToMany('Article', 'article_tag', 'tag_id', 'article_id'); } }
需要注意的是,第三个参数是本类的 id,第四个参数是第一个参数那个类的 id。
使用跟 hasMany 一样:
$tagsWithArticles = Tag::take(10)->get()->belongsToManyArticle()->get();
这里会得到一个非常复杂的对象,可以自行 `var_dump()`。跟大家说一个诀窍,`var_dump()` 以后,用 Chrome 右键 “查看源代码”,就可以看到非常整齐的对象/数组展开了。
在这里给大家展示一个少见用法(奇技淫巧):
public function parent_video() { return $this->belongsToMany($this, 'video_hierarchy', 'video_id', 'video_parent_id'); } public function children_video() { return $this->belongsToMany($this, 'video_hierarchy', 'video_parent_id', 'video_id'); }
对,你没有看错,可以 belongsToMany 自己。
其他关系
Eloquent 还提供 “远层一对多关联”、“多态关联” 和 “多态的多对多关联” 这另外三种用法,经过上面的学习,我们已经掌握了 Eloquent 模型间关系的基本概念和使用方法,剩下的几种不常用的方法就留到我们用到的时候再自己探索吧。
重要技巧:关系预载入
你也许已经发现了,在一对一关系中,如果我们需要一次性查询出10个 User 并带上对应的 Account 的话,那么就需要给数据库打 1 + 10 条 SQL,这样性能是很差的。我们可以使用一个重要的特性,关系预载入:http://laravel-china.org/docs/eloquent#eager-loading
直接上代码:
$users = User::with('hasOneAccount')->take(10)->get()
这样生成的 SQL 就是这个样子的:
select * from account where id in (1, 2, 3, ... ...)
这样 1 + 10 条 SQL 就变成了 1 + 1 条,性能大增。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
如何PHP中Laravel框架实现supervisor执行异步进程
以上是關於PHP的Laravel框架中Eloquent物件關係映射的使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!