1. 程式人生 > >Laravel Eloquent ORM--整理(詳情版)

Laravel Eloquent ORM--整理(詳情版)

介紹

Laravel 的 Eloquent ORM 提供了漂亮、簡潔的 ActiveRecord 實現來和資料庫的互動。 每個資料庫表會和一個對應的「模型」互動。

在開始之前,記得把 config/database.php 裡的資料庫連線配置好。

基本用法

我們先從建立一個 Eloquent 模型開始。模型通常放在 app 目錄下,但是您可以將它們放在任何地方,只要能通過 composer.json 自動載入。所有的 Eloquent 模型都繼承於 Illuminate\Database\Eloquent\Model .

  • 例如我放在app/Models下,則在composer.json中的配置如下:
"autoload-dev"
: { "classmap": ["tests/TestCase.php", "app/Models"] },

1. 建立[模型]

手動建立

在app/Models下新建檔案Logo.php

<?php namespace App\Model;
use Illuminate\Database\Eloquent\Model;
class Logo extends Model {}

命令建立

php artisan make:model Models/Logo -m
  • 命令建立的好處是:同時會在database/migrations 下生成對應的資料庫遷移檔案。 
    注意我們並沒有告訴 Eloquent User 模型會使用哪個資料庫表。若沒有特別指定,系統會預設自動對應名稱為「類名稱的小寫複數形態」的資料庫表。所以,在上面的例子中, Eloquent 會假設 User 模型將把資料存在 users 資料庫表。您也可以在類中定義 table 屬性自定義要對應的資料庫表。
class Logo extends Model {
    protected $table = 'my_logo';
}
  • 注意: Eloquent 也會假設每個資料庫表都有一個欄位名稱為 id 的主鍵。您可以在類裡定義 primaryKey 屬性來重寫。同樣的,您也可以定義 connection 屬性,指定模型連線到指定的資料庫連線。 
    定義好模型之後,您就可以從資料庫表新增及獲取資料了。注意在預設情況下,在資料庫表裡需要有 updated_at 和 created_at 兩個欄位。如果您不想設定或自動更新這兩個欄位,則將類裡的 $timestamps 屬性設為 false即可。
public $timestamps = false
;

2. 使用[模型]

使用模型的方法

取出所有記錄:$logos = Logo::all();

根據主鍵取出一條資料:$logos = Logo::find(1);

拆分查詢:傳到方法裡的第一個引數表示每次「拆分」要取出的資料數量。第二個引數的閉合函式會在每次取出資料時被呼叫。

User::chunk(200, function($users)
{   // 每次查詢200條
    foreach ($users as $user)
    {
        //
    }
});
  • 不一一列舉了,可以訪問:[eloquent ORM](http://laravel-china.org/docs/5.0/eloquent)
  • 如果沒辦法使用流暢介面產生出查詢語句,也可以使用 whereRaw 方法:
$users = User::whereRaw('age > ? and votes = 100', [25])->get();

軟刪除

通過軟刪除方式刪除了一個模型後,模型中的資料並不是真的從資料庫被移除。而是會設定 deleted_at時間戳。要讓模型使用軟刪除功能,只要在模型類里加入 SoftDeletingTrait 即可:

use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model {
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}

要加入 deleted_at 欄位到資料庫表,可以在遷移檔案裡使用 softDeletes 方法:

$table->softDeletes();

現在當您使用模型呼叫 delete 方法時, deleted_at欄位會被更新成現在的時間戳。在查詢使用軟刪除功能的模型時,被「刪除」的模型資料不會出現在查詢結果裡。

  • 普通查詢方法只能查詢到deleted_at為NULL的資料,也就是未被刪除/有效的資料。要強制讓已被軟刪除的模型資料出現在查詢結果裡,在查詢時使用 withTrashed 方法:
$users = User::withTrashed()->where('account_id', 1)->get();
  • 如果您只想查詢被軟刪除的模型資料,可以使用 onlyTrashed 方法:
$users = User::onlyTrashed()->where('account_id', 1)->get();
  • 要把被軟刪除的模型資料恢復,使用 restore 方法:
$user->restore();
  • 您也可以結合查詢語句使用 restore :
User::withTrashed()->where('account_id', 1)->restore();
  • 如果想要真的從模型資料庫刪除,使用 forceDelete 方法:
$user->forceDelete();
  • 要確認模型是否被軟刪除了,可以使用 trashed 方法:
if ($user->trashed())
{
    //
}

範圍查詢

定義範圍查詢

範圍查詢可以讓您輕鬆的重複利用模型的查詢邏輯。要設定範圍查詢,只要定義有 scope 字首的模型方法:

class User extends Model {
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }
    public function scopeWomen($query)
    {
        return $query->whereGender('W');
    }
}
使用範圍查詢
$users = User::popular()->women()->orderBy('created_at')->get();
動態範圍查詢

有時您可能想要定義可接受引數的範圍查詢方法。只要把引數加到方法裡:

class User extends Model {
    public function scopeOfType($query, $type)
    {
        return $query->whereType($type);
    }
}

然後把引數值傳到範圍查詢方法呼叫裡:

$users = User::ofType('member')->get();

3. 關聯

一對一

定義一對一關聯

一對一關聯是很基本的關聯。例如一個 User 模型會對應到一個 Phone 。 在 Eloquent 裡可以像下面這樣定義關聯:

class User extends Model {
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

傳到 hasOne 方法裡的第一個引數是關聯模型的類名稱。定義好關聯之後,就可以使用 Eloquent 的動態屬性取得關聯物件:

$phone = User::find(1)->phone;

SQL 會執行如下語句:

select * from users where id = 1
select * from phones where user_id = 1
  • 注意, Eloquent 假設對應的關聯模型資料庫表裡,外來鍵名稱是基於模型名稱。在這個例子裡,預設 Phone 模型資料庫表會以 user_id 作為外來鍵。如果想要更改這個預設,可以傳入第二個引數到 hasOne 方法裡。更進一步,您可以傳入第三個引數,指定關聯的外來鍵要對應到本身的哪個欄位:
return $this->hasOne('App\Phone', 'foreign_key');
return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
定義相對的關聯

要在 Phone 模型裡定義相對的關聯,可以使用 belongsTo 方法:

class Phone extends Model {
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

在上面的例子裡, Eloquent 預設會使用 phones 資料庫表的 user_id 欄位查詢關聯。如果想要自己指定外來鍵欄位,可以在 belongsTo 方法裡傳入第二個引數:

class Phone extends Model {
    public function user()
    {
        return $this->belongsTo('App\User', 'local_key');
    }
}

除此之外,也可以傳入第三個引數指定要參照上層資料庫表的哪個欄位:

class Phone extends Model {
    public function user()
    {
        return $this->belongsTo('App\User', 'local_key', 'parent_key');
    }
}

一對多

定義一對多關聯

一對多關聯的例子如,一篇 Blog 文章可能「有很多」評論。可以像這樣定義關聯:

class Post extends Model {
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

現在可以經由動態屬性取得文章的評論:

$comments = Post::find(1)->comments;

如果需要增加更多條件限制,可以在呼叫 comments 方法後面通過鏈式查詢條件方法:

$comments = Post::find(1)->comments()->where('title', '=', 'foo')->first();

同樣的,您可以傳入第二個引數到 hasMany 方法更改預設的外來鍵名稱。以及,如同 hasOne 關聯,可以指定本身的對應欄位:

return $this->hasMany('App\Comment', 'foreign_key');

return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
定義相對的關聯

要在 Comment 模型定義相對應的關聯,可使用 belongsTo 方法:

class Comment extends Model {
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}

多對多

定義多對多關聯

多對多關聯更為複雜。這種關聯的例子如,一個使用者( user )可能用有很多身份( role ),而一種身份可能很多使用者都有。例如很多使用者都是「管理者」。多對多關聯需要用到三個資料庫表: users , roles ,和 role_user 。 role_user 樞紐表命名是以相關聯的兩個模型資料庫表,依照字母順序命名,樞紐表裡面應該要有 user_id 和 role_id 欄位。

可以使用 belongsToMany 方法定義多對多關係:

class User extends Model {
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}
class Role extends Model {

    public function users()
    {
        return $this->belongsToMany('App\User');
    }

}

現在我們可以從 User 模型取得 roles:

$roles = User::find(1)->roles;

如果不想使用預設的樞紐資料庫表命名方式,可以傳遞資料庫表名稱作為 belongsToMany 方法的第二個引數:

return $this->belongsToMany('App\Role', 'user_roles');

也可以更改預設的關聯欄位名稱:

return $this->belongsToMany('App\Role', 'user_roles', 'user_id', 'role_id');

Has Many Through 遠層一對多關聯

「遠層一對多關聯」提供了方便簡短的方法,可以經由多層間的關聯取得遠層的關聯。例如,一個 Country 模型可能通過 Users 關聯到很多 Posts 模型。 資料庫表間的關係可能看起來如下:

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string

雖然 posts 資料庫表本身沒有 country_id 欄位,但 hasManyThrough 方法讓我們可以使用 $country->posts 取得 country 的 posts。我們可以定義以下關聯:

class Country extends Model {
    public function posts()
    {
        return $this->hasManyThrough('App\Post', 'App\User');
    }
}

如果想要手動指定關聯的欄位名稱,可以傳入第三和第四個引數到方法裡:

class Country extends Model {
    public function posts()
    {
        return $this->hasManyThrough('App\Post', 'App\User', 'country_id', 'user_id');
    }
}

關聯查詢

根據關聯條件查詢

在取得模型資料時,您可能想要以關聯模型作為查詢限制。例如,您可能想要取得所有「至少有一篇評論」的Blog 文章。可以使用 has 方法達成目的:

$posts = Post::has('comments')->get();

也可以指定運算子和數量:

$posts = Post::has('comments', '>=', 3)->get();

也可以使用”點號”的形式來獲取巢狀的 has 宣告:

$posts = Post::has('comments.votes')->get();

如果想要更進階的用法,可以使用 whereHas 和 orWhereHas 方法,在 has 查詢裡設定 “where” 條件 :

$posts = Post::whereHas('comments', function($q)
{
    $q->where('content', 'like', 'foo%');
})->get();

動態屬性

Eloquent 可以經由動態屬性取得關聯物件。 Eloquent 會自動進行關聯查詢,而且會很聰明的知道應該要使用 get(用在一對多關聯)或是 first (用在一對一關聯)方法。可以經由和「關聯方法名稱相同」的動態屬性取得物件。例如,如下面的模型物件 $phone:

class Phone extends Model {
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}
$phone = Phone::find(1);

您可以不用像下面這樣列印使用者的 email :echo $phone->user()->first()->email; 
而可以簡寫如下:echo $phone->user->email;

  • 若取得的是許多關聯物件,會返回 Illuminate\Database\Eloquent\Collection 物件。

預載入

預載入是用來減少 N + 1 查詢問題。例如,一個 Book 模型資料會關聯到一個 Author 。關聯會像下面這樣定義:

class Book extends Model {
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

現在考慮下面的程式碼:

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

上面的迴圈會執行一次查詢取回所有資料庫表上的書籍,然而每本書籍都會執行一次查詢取得作者。所以若我們有 25 本書,就會進行 26次查詢。

很幸運地,我們可以使用預載入大量減少查詢次數。使用 with 方法指定想要預載入的關聯物件:

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

現在,上面的迴圈總共只會執行兩次查詢:

select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)

使用預載入可以大大提高程式的效能。

當然,也可以同時載入多種關聯:

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

預載入條件限制

有時您可能想要預載入關聯,同時也想要指定載入時的查詢限制。下面有一個例子:

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

上面的例子裡,我們預載入了 user 的 posts 關聯,並限制條件為 post 的 title 欄位需包含 “first” 。

當然,預載入的閉合函式裡不一定只能加上條件限制,也可以加上排序:

$users = User::with(['posts' => function($query)
{
    $query->orderBy('created_at', 'desc');
}])->get();

新增關聯模型

附加一個關聯模型

您常常會需要加入新的關聯模型。例如新增一個 comment 到 post 。除了手動設定模型的 post_id 外來鍵, 
也可以從上層的 Post 模型新增關聯的 comment :

$comment = new Comment(['message' => 'A new comment.']);
$post = Post::find(1);
$comment = $post->comments()->save($comment);

上面的例子裡,新增的 comment 模型中 post_id 欄位會被自動設定。

如果想要同時新增很多關聯模型:

$comments = [
    new Comment(['message' => 'A new comment.']),
    new Comment(['message' => 'Another comment.']),
    new Comment(['message' => 'The latest comment.'])
];
$post = Post::find(1);
$post->comments()->saveMany($comments);

從屬關聯模型 ( Belongs To )

要更新 belongsTo 關聯時,可以使用 associate 方法。這個方法會設定子模型的外來鍵:

$account = Account::find(10);
$user->account()->associate($account);
$user->save();

相關推薦

Laravel Eloquent ORM--整理詳情

介紹Laravel 的 Eloquent ORM 提供了漂亮、簡潔的 ActiveRecord 實現來和資料庫的互動。 每個資料庫表會和一個對應的「模型」互動。在開始之前,記得把 config/database.php 裡的資料庫連線配置好。基本用法我們先從建立一個 Eloq

Laravel Eloquent ORM--整理(未轉)

net article -- sdn com .net csdn shu lar 轉:http://blog.csdn.net/a437629292/article/details/46312695 http://www.jianshu

教你做一個單機人事管理系統Winformtreeview與listview使用詳情

不讓 ogr lena 位置 exc bject tel horizon raw ------------------------------------------------------------------部門部分--------------------------

2018OCP 11g 052最新考試題庫整理帶答案3

註冊 ble 考試 rar data 試題 rman pac tip 3、Which structure can span multiple data files? A) a permanent tablespace B) a bigfile tablespace C) a

2018OCP 11g 052最新考試題庫整理帶答案2

The info RoCE inf auto tom per res sta 2、Which two are true about Optimizer Statistics? A) They do not persist across Instance restarts.

2018OCP 11g 052最新考試題庫整理帶答案4

per sub tab ase bulk ocp nvi mit who 4、For which requirement should you configure shared servers? A) accommodating an increasing number o

2018OCP 11g 052最新考試題庫整理帶答案5

existing answer tables ive ble ret start rec ocp 5、Which two affect the time taken for instance recovery? A) size of redo logs B) size of

2018OCP 11g 052最新考試題庫整理帶答案7

ons oracle segment apu opera cuug 試題 tab ora 7、Which is true about external tables? A) The ORACLE_DATAPUMP access driver can be used to w

2018OCP 11g 052最新考試題庫整理帶答案8

整理 data sid gem red mod 答案 answer hive 8、Which two are true about the Fast Recovery Area (FRA)? A) It should be larger than the database.

2018OCP 11g 052最新考試題庫整理帶答案9

mat ace set ont manually var serve acl ria 9、Which is true about the Automatic Diagnostic Repository (ADR)? A) It includes diagnostic dat

2018OCP 11g 052最新考試題庫整理帶答案10

true med recovery pen nds open cat answer base 10、Which two are true about consistent database backups? A) They can only be taken when a

2018OCP 11g 052最新考試題庫整理帶答案11

com recover date update mit cover ransac tables nsa 11、Which three are true about UNDO data? A) It is used to roll back failed transactio

2018OCP 11g 052最新考試題庫整理帶答案13

set eat eve ever level ret swe 試題 can 13、Which two are true about AWR snapshots? A) They are stored In the SYSAUX tablespace. B) They are

2018OCP 11g 052最新考試題庫整理帶答案12

star rest cor nts ted ever value cal critical 12、Which two types of Information can be found in the alert log? A) instance recovery detai

2018OCP 11g 052最新考試題庫整理帶答案14

taf list port 考試 copies obs swe form 答案 14、Which command is used to display files that no longer conform to the backup retention policy?

2018OCP 11g 052最新考試題庫整理帶答案15

rac lists manual ica for 最新 prevent bitmap 試題 15、Which two are true about space management in tablespaces? A) Locally managed tablespaces

2018OCP 11g 052最新考試題庫整理帶答案16

com 考試題 buffers pro 11g ack per switch int 16、Which two events always request the LGWR to write? A) when LGWR is notified by a server pro

2018OCP 11g 052最新考試題庫整理帶答案17

exe min where ans restart comm nds turned play 17、 Examine these commands and their output: SQL> SELECT * FROM emp; ENO ENAME 100 Ada

2018OCP 11g 052最新考試題庫整理帶答案18

北京 file cuug nat ack ble sys des rec 18、Where Is backup metadata stored for use by Recovery Manager (RMAN)? A) In the control file B) In

2018OCP 11g 052最新考試題庫整理帶答案

red orm con flashback rman ack 北京 log 11g 19、Which two can be backed up by using RMAN when a database Is open in ARCHIVELOG mode, so that