本篇文章整理分享六個(gè)能提高代碼可讀性的 laravel eloquent 小技巧,希望對(duì)大家有所幫助!
Eloquent是laravel默認(rèn)使用的ORM。采用了活動(dòng)記錄模式。讓你可以以一種更加輕松的方式與數(shù)據(jù)庫(kù)進(jìn)行交互。每個(gè)單獨(dú)的模型都表示數(shù)據(jù)庫(kù)中的一個(gè)表,你可以使用該表進(jìn)行操作。在這篇文章中,我們將或多或少地向你展示你可能不知道的隱藏秘密、方法和屬性,以改進(jìn)你的代碼。
蛇形命名 屬性
蛇形命名屬性是一個(gè)有趣的屬性。讓我們看看代碼是怎么說(shuō)的:
/** ?*?指示是否在數(shù)組上使用蛇形大小寫(xiě)屬性。 ?* ?*?@var?bool ?*/ public?static?$snakeAttributes?=?true;
人們經(jīng)常會(huì)錯(cuò)誤地使用這個(gè)屬性來(lái)更改訪問(wèn)屬性的方式。許多人認(rèn)為,如果更改這個(gè)屬性,就可以使用駝峰式注釋輕松訪問(wèn)屬性。事實(shí)并非如此。我們強(qiáng)烈建議你不要使用它。當(dāng)模型作為數(shù)組輸出時(shí),只需定義屬性是駝峰式還是蛇形即可。
如果你想基于駝峰式命名,我們建議你查看 Kirk Bushell 的軟件包 Eloquence by Kirk Bushell.
分頁(yè)
如果你正在使用 Laravel 的 Eloquent ORM,那這對(duì)你是個(gè)好消息。 它提供了一種開(kāi)箱即用的分頁(yè)方法。你可能很熟悉這樣的寫(xiě)法:
$comments?=?Comment::paginate(20);
使用此方法,你可以每頁(yè)20個(gè)條目來(lái)為 comment model 分頁(yè)。更改該值可以定義每頁(yè)顯示多少條數(shù)。如果不指定任何內(nèi)容,則應(yīng)用默認(rèn)值,即15。
假設(shè)您希望在網(wǎng)站上的多個(gè)位置顯示評(píng)論。每頁(yè)總是有30條評(píng)論。如果必須在每個(gè)地方傳遞參數(shù)30,那就麻煩了。因此,您可以直接在模型上設(shè)置新的默認(rèn)值。
protected?$perPage?=?30;
在model里面增加自定義值
Eloquent有一個(gè)稱(chēng)為“訪問(wèn)器”的強(qiáng)大功能。該功能允許你向模型或表中不存在的模型添加自定義字段。使用現(xiàn)有的值或定義全新的值都不重要,隨時(shí)都可以回退。下面是訪問(wèn)器如何工作的示例。假設(shè)有一個(gè)名為user的模型,我們給他添加一個(gè)FullName的訪問(wèn)器:
function?getFullNameAttribute()?{ ????return?sprintf('%s?%s',?$this->first_name,?$this->last_name); }
現(xiàn)在你可以訪問(wèn)post模型上的full_name屬性,如下:
User::latest()->first()->full_name;
如果返回對(duì)象(如集合),則此屬性不會(huì)附加到用戶(hù)模型。將protected$appends屬性添加到模型中。它接受一個(gè)數(shù)組,其中包含一個(gè)或多個(gè)字段,從現(xiàn)在起應(yīng)該自動(dòng)追加這些字段。寫(xiě)成這樣就可以了:
protected?$appends?=?['full_name'];
為不存在列增加一個(gè)變異器(屬性設(shè)置器)
變異器與獲取器相反。你可以用它做些很有意思的事情。 舉個(gè)例子,轉(zhuǎn)換不同類(lèi)型的輸入。 讓我來(lái)給你詳細(xì)說(shuō)說(shuō)。假設(shè)你想要保存一種類(lèi)型的時(shí)間段。通常,你總是保存盡可能小的單位。在我們的案例中是秒。由于UX的原因,用戶(hù)不想輸入秒,例如在一個(gè)地方輸入分鐘,或者在另一個(gè)地方輸入小時(shí)。這一切都可以很快解決。
class?Video?extends?Model { ????public?function?setDurationInMinutes($value) ????{ ????????$this->attributes['duration_in_seconds']?=?$value?*?60; ????} ????public?function?setDurationInHours($value) ????{ ????????$this->attributes['duration_in_seconds']?=?$value?*?60?*?60; ????} }
上述代碼意味著你可以使用一個(gè)不存在于數(shù)據(jù)表本身的字段。
model中使用的是duration_in_minutes字段,但是在后臺(tái),我們使用duration_in_seconds進(jìn)行更新,也有可能使用一個(gè)不存在字段duration_in_hours。根據(jù)這個(gè)邏輯,我們?cè)贑ontroller如此調(diào)用:
class?AnyController { ????public?function?store() ????{ ????????$video->update([ ????????????'title'?=>?request('title'), ????????????'duration_in_minutes'?=>?request('duration_in_minutes'), ????????]); ????} }
這將節(jié)省你在控制器中進(jìn)行計(jì)算的時(shí)間,你可以簡(jiǎn)單地使用不存在的列,并在執(zhí)行某些計(jì)算時(shí)使用變異器將其結(jié)果映射到正確的字段上。
渴求式加載: with $with
讓我們來(lái)談?wù)勱P(guān)聯(lián)關(guān)系。默認(rèn)情況下,Laravel使用延遲加載。就關(guān)聯(lián)關(guān)系而言,這意味著什么?延遲加載的好處是可以節(jié)省內(nèi)存,因?yàn)椴⒉皇撬械臄?shù)據(jù)都需要保留,我們可以在需要的時(shí)候加載數(shù)據(jù)。如下:
$comments?=?Comment::all(); foreach?($comments?as?$comment)?{ ????echo?$comment->user->name; }
在上面的例子中,我們會(huì)獲取所有評(píng)論數(shù)據(jù)。然后遍歷評(píng)論并顯示每個(gè)評(píng)論的用戶(hù)名。這段代碼沒(méi)什么問(wèn)題,可以正常工作,但我們遇到了一個(gè)問(wèn)題。延遲加載現(xiàn)在確保僅當(dāng)我們想要輸出用戶(hù)名時(shí)才執(zhí)行獲取用戶(hù)的查詢(xún)。
歡迎來(lái)到你的第一個(gè) N+1 問(wèn)題。為什么是 N+1?N 始終是評(píng)論的數(shù)量,1 是獲取評(píng)論的查詢(xún)。例如,如果我們有500個(gè)評(píng)論,那么獲取所有評(píng)論的查詢(xún)被觸發(fā)一次,然后一個(gè)查詢(xún)獲得相應(yīng)的user-per評(píng)論。所以500+1查詢(xún)。這意味著隨著注釋數(shù)量的增加,查詢(xún)的數(shù)量也會(huì)增加。
為了防止出現(xiàn)這種情況,有一種稱(chēng)為渴求式加載的方法。
$comments?=?Comment::with('user')->get(); foreach?($comments?as?$comment)?{ ????echo?$comment->user->name; }
這會(huì)以?xún)蓚€(gè)查詢(xún)結(jié)束。第一個(gè)查詢(xún)獲取所有注釋?zhuān)诙€(gè)查詢(xún)立即獲取所有關(guān)聯(lián)用戶(hù)。在后臺(tái),會(huì)發(fā)生以下情況(簡(jiǎn)化版SQL):
SELECT?id,?user_id,?body?FROM?comments; SELECT?name?FROM?users?WHERE?user_id?IN?(1,2,3,4,5...);
不論是 10、500 還是 10000 條評(píng)論數(shù)據(jù)都不重要,我們都依舊只執(zhí)行兩次SQL查詢(xún)。
好了,你現(xiàn)在已經(jīng)看到如何使用渴求式加載了。但只限于如何手動(dòng)使用。你還可以將整個(gè)過(guò)程自動(dòng)化,以便某些關(guān)聯(lián)關(guān)系總是自動(dòng)通過(guò)渴求式方式加載。為此,需要給模型設(shè)定一個(gè)屬性。
protected?$with?=?[];
我們可以在Comment model簡(jiǎn)單設(shè)置 protected $with = [‘user’];, 從現(xiàn)在起,user在任何時(shí)候都會(huì)自動(dòng)加載。
我們還有很多種渴求式加載,有僅加載特定列、嵌套即時(shí)加載、多個(gè)即時(shí)加載等等。更多詳情請(qǐng)Laravel文檔或深入核心。
modelKeys 方法
有的時(shí)候需要查詢(xún)所有的主鍵 ID, 查詢(xún)是否復(fù)雜并不重要,大多數(shù)人可能會(huì)像這樣做:
User::all()->pluck('id');
這個(gè)操作很 nice,但是返回的是一個(gè)集合,想要轉(zhuǎn)換成數(shù)組的話(huà)可以使用 toArray()。
User::all()->pluck('id')->toArray();
大多數(shù)情況下,上面的操作的可以簡(jiǎn)化成這樣:
User::all()->modelKeys();
這種方式返回一個(gè)數(shù)組。重要的是這個(gè)方法并不會(huì)總是返回 id。 顧名思義,他是以數(shù)組的形式返回所有模型主鍵。主鍵默認(rèn)是id,同時(shí)也可以在模型中定義主鍵名。
protected?$primaryKey?=?'id';
原文地址:https://laravel-news.com/6-eloquent-secrets譯文地址:https://www.php.cn/link/c7decb5ce28209911b545d0b1059c5e3
【相關(guān)推薦:Eloquence】