成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Laravel & Lumen之Eloquent ORM使用速查-進(jìn)階部分

Chaz / 2447人閱讀

摘要:關(guān)聯(lián)關(guān)系查詢在中,所有的關(guān)系都是使用函數(shù)定義的,可以在不執(zhí)行關(guān)聯(lián)查詢的情況下獲取關(guān)聯(lián)的實例。

關(guān)聯(lián)關(guān)系 One To One

假設(shè)User模型關(guān)聯(lián)了Phone模型,要定義這樣一個關(guān)聯(lián),需要在User模型中定義一個phone方法,該方法返回一個hasOne方法定義的關(guān)聯(lián)

hasOne("AppPhone");
    }
}

hasOne方法的第一個參數(shù)為要關(guān)聯(lián)的模型,定義好之后,可以使用下列語法查詢到關(guān)聯(lián)屬性了

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

Eloquent會假定關(guān)聯(lián)的外鍵是基于模型名稱的,因此Phone模型會自動使用user_id字段作為外鍵,可以使用第二個參數(shù)和第三個參數(shù)覆蓋

return $this->hasOne("AppPhone", "foreign_key");
return $this->hasOne("AppPhone", "foreign_key", "local_key");
定義反向關(guān)系

定義上述的模型之后,就可以使用User模型獲取Phone模型了,當(dāng)然也可以通過Phone模型獲取所屬的User了,這就用到了belongsTo方法了

belongsTo("AppUser");
        // return $this->belongsTo("AppUser", "foreign_key");
        // return $this->belongsTo("AppUser", "foreign_key", "other_key");

    }
}
One To Many

假設(shè)有一個帖子,它有很多關(guān)聯(lián)的評論信息,這種情況下應(yīng)該使用一對多的關(guān)聯(lián),使用hasMany方法

hasMany("AppComment");
    }
}

查詢操作

$comments = AppPost::find(1)->comments;
foreach ($comments as $comment) {
    //
}

$comments = AppPost::find(1)->comments()->where("title", "foo")->first();
定義反向關(guān)聯(lián)

反向關(guān)聯(lián)也是使用belongsTo方法,參考One To One部分。

$comment = AppComment::find(1);
echo $comment->post->title;
Many To Many

多對多關(guān)聯(lián)因為多了一個中間表,實現(xiàn)起來比hasOnehasMany復(fù)雜一些。

考慮這樣一個場景,用戶可以屬于多個角色,一個角色也可以屬于多個用戶。這就引入了三個表: users, roles, role_user。其中role_user表為關(guān)聯(lián)表,包含兩個字段user_idrole_id。

多對多關(guān)聯(lián)需要使用belongsToMany方法

belongsToMany("AppRole", "role_user");
        // 指定關(guān)聯(lián)表,關(guān)聯(lián)字段
        // return $this->belongsToMany("AppRole", "role_user", "user_id", "role_id");

        return $this->belongsToMany("AppRole");
    }
}

上述定義了一個用戶屬于多個角色,一旦該關(guān)系確立,就可以查詢了

$user = AppUser::find(1);
foreach ($user->roles as $role) {
    //
}

$roles = AppUser::find(1)->roles()->orderBy("name")->get();
反向關(guān)聯(lián)關(guān)系

反向關(guān)系與正向關(guān)系實現(xiàn)一樣

belongsToMany("AppUser");
    }
}
檢索中間表的列值

對多對多關(guān)系來說,引入了一個中間表,因此需要有方法能夠查詢到中間表的列值,比如關(guān)系確立的時間等,使用pivot屬性查詢中間表

$user = AppUser::find(1);

foreach ($user->roles as $role) {
    echo $role->pivot->created_at;
}

上述代碼訪問了中間表的created_at字段。

注意的是,默認(rèn)情況下之后模型的鍵可以通過pivot對象進(jìn)行訪問,如果中間表包含了額外的屬性,在指定關(guān)聯(lián)關(guān)系的時候,需要使用withPivot方法明確的指定列名

return $this->belongsToMany("AppRole")->withPivot("column1", "column2");

如果希望中間表自動維護(hù)created_atupdated_at字段的話,需要使用withTimestamps()

return $this->belongsToMany("AppRole")->withTimestamps();
Has Many Through

這種關(guān)系比較強大,假設(shè)這樣一個場景:Country模型下包含了多個User模型,而每個User模型又包含了多個Post模型,也就是說一個國家有很多用戶,而這些用戶都有很多帖子,我們希望查詢某個國家的所有帖子,怎么實現(xiàn)呢,這就用到了Has Many Through關(guān)系

countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string

可以看到,posts表中并不直接包含country_id,但是它通過users表與countries表建立了關(guān)系

使用Has Many Through關(guān)系

namespace App;

use IlluminateDatabaseEloquentModel;

class Country extends Model
{

    public function posts()
    {
        // return $this->hasManyThrough("AppPost", "AppUser", "country_id", "user_id");

        return $this->hasManyThrough("AppPost", "AppUser");
    }
}

方法hasManyThrough的第一個參數(shù)是我們希望訪問的模型名稱,第二個參數(shù)是中間模型名稱。

HasManyThrough hasManyThrough( 
    string $related, 
    string $through, 
    string|null $firstKey = null, 
    string|null $secondKey = null, 
    string|null $localKey = null
)
Polymorphic Relations (多態(tài)關(guān)聯(lián))

多態(tài)關(guān)聯(lián)使得同一個模型使用一個關(guān)聯(lián)就可以屬于多個不同的模型,假設(shè)這樣一個場景,我們有一個帖子表和一個評論表,用戶既可以對帖子執(zhí)行喜歡操作,也可以對評論執(zhí)行喜歡操作,這樣的情況下該怎么處理呢?

表結(jié)構(gòu)如下

posts
    id - integer
    title - string
    body - text

comments
    id - integer
    post_id - integer
    body - text

likes
    id - integer
    likeable_id - integer
    likeable_type - string

可以看到,我們使用likes表中的likeable_type字段判斷該記錄喜歡的是帖子還是評論,表結(jié)構(gòu)有了,接下來就該定義模型了

morphTo();
    }
}

class Post extends Model
{

    public function likes()
    {
        return $this->morphMany("AppLike", "likeable");
    }
}

class Comment extends Model
{

    public function likes()
    {
        return $this->morphMany("AppLike", "likeable");
    }
}

默認(rèn)情況下,likeable_type的類型是關(guān)聯(lián)的模型的完整名稱,比如這里就是AppPostAppComment。

通常情況下我們可能會使用自定義的值標(biāo)識關(guān)聯(lián)的表名,因此,這就需要自定義這個值了,我們需要在項目的服務(wù)提供者對象的boot方法中注冊關(guān)聯(lián)關(guān)系,比如AppServiceProviderboot方法中

use IlluminateDatabaseEloquentRelationsRelation;

Relation::morphMap([
    "posts" => AppPost::class,
    "likes" => AppLike::class,
]);
檢索多態(tài)關(guān)系

訪問一個帖子所有的喜歡

$post = AppPost::find(1);  
foreach ($post->likes as $like) {
    //
}

訪問一個喜歡的帖子或者評論

$like = AppLike::find(1);   
$likeable = $like->likeable;

上面的例子中,返回的likeable會根據(jù)該記錄的類型返回帖子或者評論。

多對多的多態(tài)關(guān)聯(lián)

多對多的關(guān)聯(lián)使用方法morphToManymorphedByMany,這里就不多廢話了。

關(guān)聯(lián)關(guān)系查詢

在Eloquent中,所有的關(guān)系都是使用函數(shù)定義的,可以在不執(zhí)行關(guān)聯(lián)查詢的情況下獲取關(guān)聯(lián)的實例。假設(shè)我們有一個博客系統(tǒng),User模型關(guān)聯(lián)了很多Post模型:

public function posts()
{
   return $this->hasMany("AppPost");
}

你可以像下面這樣查詢關(guān)聯(lián)并且添加額外的約束

$user = AppUser::find(1);
$user->posts()->where("active", 1)->get();

如果不需要對關(guān)聯(lián)的屬性添加約束,可以直接作為模型的屬性訪問,例如上面的例子,我們可以使用下面的方式訪問User的Post

$user = AppUser::find(1);
foreach ($user->posts as $post) {
    //
}

動態(tài)的屬性都是延遲加載的,它們只有在被訪問的時候才會去查詢數(shù)據(jù)庫,與之對應(yīng)的是預(yù)加載,預(yù)加載可以使用關(guān)聯(lián)查詢出所有數(shù)據(jù),減少執(zhí)行sql的數(shù)量。

查詢關(guān)系存在性

使用has方法可以基于關(guān)系的存在性返回結(jié)果

// 檢索至少有一個評論的所有帖子...
$posts = AppPost::has("comments")->get();

// Retrieve all posts that have three or more comments...
$posts = Post::has("comments", ">=", 3)->get();
// Retrieve all posts that have at least one comment with votes...
$posts = Post::has("comments.votes")->get();

如果需要更加強大的功能,可以使用whereHasorWhereHas方法,把where條件放到has語句中。

// 檢索所有至少存在一個匹配foo%的評論的帖子
$posts = Post::whereHas("comments", function ($query) {
    $query->where("content", "like", "foo%");
})->get();
預(yù)加載

在訪問Eloquent模型的時候,默認(rèn)情況下所有的關(guān)聯(lián)關(guān)系都是延遲加載的,在使用的時候才會開始加載,這就造成了需要執(zhí)行大量的sql的問題,使用預(yù)加載功能可以使用關(guān)聯(lián)查詢出所有結(jié)果

belongsTo("AppAuthor");
    }
}

接下來我們檢索所有的書和他們的作者

$books = AppBook::all();

foreach ($books as $book) {
    echo $book->author->name;
}

上面的查詢將會執(zhí)行一個查詢查詢出所有的書,然后在遍歷的時候再執(zhí)行N個查詢查詢出作者信息,顯然這樣做是非常低效的,幸好我們還有預(yù)加載功能,可以將這N+1個查詢減少到2個查詢,在查詢的時候,可以使用with方法指定哪個關(guān)系需要預(yù)加載。

$books = AppBook::with("author")->get();
foreach ($books as $book) {
    echo $book->author->name;
}

對于該操作,會執(zhí)行下列兩個sql

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

預(yù)加載多個關(guān)系

$books = AppBook::with("author", "publisher")->get();

嵌套的預(yù)加載

$books = AppBook::with("author.contacts")->get();
帶約束的預(yù)加載
$users = AppUser::with(["posts" => function ($query) {
    $query->where("title", "like", "%first%");
}])->get();

$users = AppUser::with(["posts" => function ($query) {
    $query->orderBy("created_at", "desc");
}])->get();
延遲預(yù)加載

有時候,在上級模型已經(jīng)檢索出來之后,可能會需要預(yù)加載關(guān)聯(lián)數(shù)據(jù),可以使用load方法

$books = AppBook::all();
if ($someCondition) {
    $books->load("author", "publisher");
}

$books->load(["author" => function ($query) {
    $query->orderBy("published_date", "asc");
}]);
關(guān)聯(lián)模型插入 save方法

保存單個關(guān)聯(lián)模型

$comment = new AppComment(["message" => "A new comment."]);
$post = AppPost::find(1);
$post->comments()->save($comment);

保存多個關(guān)聯(lián)模型

$post = AppPost::find(1); 
$post->comments()->saveMany([
    new AppComment(["message" => "A new comment."]),
    new AppComment(["message" => "Another comment."]),
]);
save方法和多對多關(guān)聯(lián)

多對多關(guān)聯(lián)可以為save的第二個參數(shù)指定關(guān)聯(lián)表中的屬性

AppUser::find(1)->roles()->save($role, ["expires" => $expires]);

上述代碼會更新中間表的expires字段。

create方法

使用create方法與save方法的不同在于它是使用數(shù)組的形式創(chuàng)建關(guān)聯(lián)模型的

$post = AppPost::find(1);
$comment = $post->comments()->create([
    "message" => "A new comment.",
]);
更新 "Belongs To" 關(guān)系

更新belongsTo關(guān)系的時候,可以使用associate方法,該方法會設(shè)置子模型的外鍵

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

要移除belongsTo關(guān)系的話,使用dissociate方法

$user->account()->dissociate();
$user->save();
Many to Many 關(guān)系 中間表查詢條件

當(dāng)查詢時需要對使用中間表作為查詢條件時,可以使用wherePivot, wherePivotIn,orWherePivot,orWherePivotIn添加查詢條件。

$enterprise->with(["favorites" => function($query) {
    $query->wherePivot("enterprise_id", "=", 12)->select("id");
}]);
Attaching / Detaching
$user = AppUser::find(1);
// 為用戶添加角色
$user->roles()->attach($roleId);
// 為用戶添加角色,更新中間表的expires字段
$user->roles()->attach($roleId, ["expires" => $expires]);

// 移除用戶的單個角色
$user->roles()->detach($roleId);
// 移除用戶的所有角色
$user->roles()->detach();

attachdetach方法支持?jǐn)?shù)組參數(shù),同時添加和移除多個

$user = AppUser::find(1);
$user->roles()->detach([1, 2, 3]);
$user->roles()->attach([1 => ["expires" => $expires], 2, 3]);
更新中間表(關(guān)聯(lián)表)字段

使用updateExistingPivot方法更新中間表

$user = AppUser::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
同步中間表(同步關(guān)聯(lián)關(guān)系)

使用sync方法,可以指定兩個模型之間只存在指定的關(guān)聯(lián)關(guān)系

$user->roles()->sync([1, 2, 3]);
$user->roles()->sync([1 => ["expires" => true], 2, 3]);

上述兩個方法都會讓用戶只存在1,2,3三個角色,如果用戶之前存在其他角色,則會被刪除。

更新父模型的時間戳

假設(shè)場景如下,我們?yōu)橐粋€帖子增加了一個新的評論,我們希望這個時候帖子的更新時間會相應(yīng)的改變,這種行為在Eloquent中是非常容易實現(xiàn)的。

在子模型中使用$touches屬性實現(xiàn)該功能

belongsTo("AppPost");
    }
}

現(xiàn)在,更新評論的時候,帖子的updated_at字段也會被更新

$comment = AppComment::find(1);
$comment->text = "Edit to this comment!";
$comment->save();

參考: Eloquent: Relationships

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/21723.html

相關(guān)文章

  • Laravel & LumenEloquent ORM使用速查-基礎(chǔ)部分

    摘要:使用時,數(shù)據(jù)庫查詢構(gòu)造器的方法對模型類也是也用的,使用上只是省略了表名部分。在模型中使用成員變量指定綁定的表名。 使用Eloquent [el?kw?nt] 時,數(shù)據(jù)庫查詢構(gòu)造器的方法對模型類也是也用的,使用上只是省略了DB::table(表名)部分。 在模型中使用protected成員變量$table指定綁定的表名。

    NervosNetwork 評論0 收藏0
  • Laravel & LumenEloquent ORM使用速查-高級部分

    摘要:使用全局作用域功能可以為模型的所有操作增加約束。提供了一些方法可以方便的來實現(xiàn)數(shù)據(jù)類型之間的轉(zhuǎn)換。要定義一個,需要在模型中創(chuàng)建一個名稱為的方法,其中的是駝峰命名法的字段名。 查詢作用域 全局作用域 全局作用域允許你對給定模型的所有查詢添加約束。使用全局作用域功能可以為模型的所有操作增加約束。 軟刪除功能實際上就是利用了全局作用域功能 實現(xiàn)一個全局作用域功能只需要定義一個實現(xiàn)Illumi...

    BigNerdCoding 評論0 收藏0
  • Laravel & Lumen 數(shù)據(jù)庫操作速查

    摘要:在中執(zhí)行數(shù)據(jù)庫操作有兩種方式,一種是使用外觀對象的靜態(tài)方法直接執(zhí)行查詢,另外一種是使用類的靜態(tài)方法實際上也是的實現(xiàn),使用靜態(tài)訪問方式訪問的方法,內(nèi)部采用了魔術(shù)方法代理了對成員方法的訪問。在閉包函數(shù)中,如果返回,則會停止后續(xù)的處理。 在Laravel中執(zhí)行數(shù)據(jù)庫操作有兩種方式,一種是使用DB外觀對象的靜態(tài)方法直接執(zhí)行sql查詢,另外一種是使用Model類的靜態(tài)方法(實際上也是Facade...

    用戶83 評論0 收藏0
  • Lumen 初體驗(二)

    摘要:的現(xiàn)狀目前是版本,是基于開發(fā)。入口文件啟動文件和配置文件框架的入口文件是。在路由中指定控制器類必須寫全命名空間,不然會提示找不到類。目前支持四種數(shù)據(jù)庫系統(tǒng)以及。使用時發(fā)生錯誤,因為在文件中,的默認(rèn)驅(qū)動是。 最近使用 Lumen 做了 2 個業(yè)余項目,特此記錄和分享一下。 Lumen 的介紹 在使用一項新的技術(shù)時,了解其應(yīng)用場景是首要的事情。 Lumen 的口號:為速度而生的 La...

    Cheriselalala 評論0 收藏0
  • Lumen---為速度而生的 Laravel 框架

    摘要:什么是官網(wǎng)是一個由組件搭建而成的微框架是當(dāng)前最快的框架之一在什么時候使用專為微服務(wù)或者設(shè)計舉個例子如果你的應(yīng)用里面有部分業(yè)務(wù)邏輯的請求頻率比較高就可以單獨把這部分業(yè)務(wù)邏輯拿出來使用來構(gòu)建一個小因為是對優(yōu)化了框架的加載機制所以對資源的要求少很 什么是 Lumen?官網(wǎng) lumen 是一個由 Laravel 組件搭建而成的微框架,是當(dāng)前最快的 PHP 框架之一! 在什么時候使用 Lume...

    104828720 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<