本文來自pilishen.com---- 原文連接; 歡迎做客咱們的php&Laravel學習羣:109256050
最簡單的,laravel裏get()獲得的是一組數據,first()獲得的是一個model數據。php
從形式上,laravel裏每個model數據(record),在取出的時候都是用的PHP的stdClass來包裹或封裝,一個model數據就是一個stdClass,stdClass是一個沒有屬性和方法的空類,通常用來建立一個匿名對象或將非對象類型轉換成對象,這樣咱們就能夠很放便的操做它,動態的添加、刪除屬性:laravel
//實例化一個空對象 $obj = new stdClass(); //給對象動態添加屬性或者方法 $obj->name = 'pilishen.com'; $obj->description = '作全球最好的IT實戰教程';
那麼,當有多條數據取出來的時候,也即有多個stdClass的時候,咱們怎麼來展示或包裹呢?就是Collection,集合的意思。數組
因此,進一步說,在model數據調取中,laravel first()取到的就是一個stdClass,而get()取到的是多個stdclass,無非是以Collection的形式包裹了起來,下面舉個類子列出全部省份:post
能夠看到,由於是取出多條數據,因此返回的是一個Collection{}
對象,裏面包含一個items[]
數組(序列),在這個序列裏,裝的就是每個stdClass{}
對象,也即具體的每個Province
數據。性能
咱們再來打印一下first()方法獲取的結果學習
咱們能夠看到first()方法獲得的直接是一個stdClass對象,由於它外層沒有array
包裹了,因此就能夠直接在其上面獲取各類屬性了,好比說能夠直接來調用關係(relationship)了,假設咱們建立一個 Province hasMany City
的例子:spa
這樣咱們就可使用 Province::fisrt()->cities()
來獲取第一個省所屬的全部城市,那若是須要獲取 id爲n 的省的全部城市的話咱們可使用 Province::find(n)->cities()
, 這裏的find()方法獲得的也是一個具體到ID了的stdClass 對象。3d
這裏注意的是,關係(eloquent relationship)的調用只能做用於某個具體的Model對象,也即你只有具體到某個Model,某個ID,或者說某個stdclass對象了,才能進一步去調用其所屬的關係,而不能直接去一堆Model數據上調用關係,或者說不能直接在一個大的collection對象後面直接取關係, 也即這樣Province::get()->cities()
是不對的,這至關於Collection{}->cities()
,而這個Collection{}
自己並無cities()
這個關係屬性,雖然它裏面的每個Province model item
擁有這個關係屬性,但那就隔着一層了。code
好吧,不能在get()
後面直接調取關係,或者說不能籠統地在一堆數據上直接調取關係,那麼,調取關係的正確姿式有哪些?對象
first() last() find() firstOrFail() findOrFail()
這些具體到ID的方法後面直接取關係,好比Province::fisrt()->cities()
get()
了,也即已經有一堆數據了,那麼能夠遍歷之後再取每個的關係,好比:$pros = Province::get(); //或者all() foreach($pros as $pro){ $pro->cities(); }
n+1
個query,當你數據不少的時候,就會致使頁面特別慢,因此你一旦意識到要在視圖裏取關係屬性,就要在Controller裏提早用with方法來預加載全部的關係,例如這樣:$pros = Province::with('cities')->get(); //或者all() foreach($pros as $pro){ $pro->cities(); }
這樣的話,一次性地取得了全部省份以及每一個省份下面的城市關係,背後只是執行了2次query,你在視圖裏再去遍歷的時候,就不用再執行數據查詢了,性能就會有較大提高。
不少小白抱怨laravel視圖加載慢,不知道他們有沒有查看一下本身頁面的query執行狀況呢?一個視圖查詢太多的query,換誰都慢~
固然呢,這些細節其實在咱們的實戰系列課程裏都已經講過了,尚未上車的童鞋,你還在等什麼呢?