天天看點

laravel中get()與 first()差別、collection與stdClass的差別

簡單的,laravel裡get()得到的是一組資料,first()得到的是一個model資料。

從形式上,laravel裡每一個model資料(record),在取出的時候都是用的PHP的stdClass來包裹或封裝,一個model資料就是一個stdClass,stdClass是一個沒有屬性和方法的空類,一般用來建立一個匿名對象或将非對象類型轉換成對象,這樣我們就可以很放便的操作它,動态的添加、删除屬性:

//執行個體化一個空對象
$obj = new stdClass();
//給對象動态添加屬性或者方法
$obj->name = 'pilishen.com';
$obj->description = '做全球最好的IT實戰教程';

           

那麼,當有多條資料取出來的時候,也即有多個stdClass的時候,我們怎麼來展現或包裹呢?就是Collection,集合的意思。

laravel中get()與 first()差別、collection與stdClass的差別

是以,進一步說,在model資料調取中,laravel first()取到的就是一個stdClass,而get()取到的是多個stdclass,無非是以Collection的形式包裹了起來,下面舉個類子列出所有省份:

laravel中get()與 first()差別、collection與stdClass的差別
laravel中get()與 first()差別、collection與stdClass的差別

可以看到,因為是取出多條資料,是以傳回的是一個

Collection{}

對象,裡面包含一個

items[]

數組(序列),在這個序列裡,裝的就是每一個

stdClass{}

對象,也即具體的每一個

Province

資料。

我們再來列印一下first()方法擷取的結果

laravel中get()與 first()差別、collection與stdClass的差別

我們可以看到first()方法得到的直接是一個stdClass對象,因為它外層沒有

array

包裹了,是以就可以直接在其上面擷取各種屬性了,比如說可以直接來調用關系(relationship)了,假設我們建立一個 

Province hasMany City

 的例子:

laravel中get()與 first()差別、collection與stdClass的差別

這樣我們就可以使用 

Province::fisrt()->cities()

來擷取第一個省所屬的所有城市,那如果需要擷取 id為n 的省的所有城市的話我們可以使用 

Province::find(n)->cities()

, 這裡的find()方法得到的也是一個具體到ID了的stdClass 對象。

這裡注意的是,關系(eloquent relationship)的調用隻能作用于某個具體的Model對象,也即你隻有具體到某個Model,某個ID,或者說某個stdclass對象了,才能進一步去調用其所屬的關系,而不能直接去一堆Model資料上調用關系,或者說不能直接在一個大的collection對象後面直接取關系, 也即這樣

Province::get()->cities()

是不對的,這相當于

Collection{}->cities()

,而這個

Collection{}

本身并沒有

cities()

這個關系屬性,雖然它裡面的每一個

Province model item

擁有這個關系屬性,但那就隔着一層了。

  1. 你可以在

    first() last() find() firstOrFail() findOrFail()

    這些具體到ID的方法後面直接取關系,比如

    Province::fisrt()->cities()

  2. 如果你已經

    get()

    了,也即已經有一堆資料了,那麼可以周遊以後再取每一個的關系,比如:
$pros = Province::get();   //或者all()
foreach($pros as $pro){
  $pro->cities();
}
           
  1. 當然,如果你是要在Blade視圖裡使用周遊後的關系資料,因為每有一個資料,就要取一次關系,就要執行一次查詢,是以你foreach裡有n個資料,就查詢n遍,就有n個query,再加上你之前get()所有資料的那1個query,是以你頁面上總共有

    n+1

    個query,當你資料很多的時候,就會導緻頁面特别慢,是以你一旦意識到要在視圖裡取關系屬性,就要在Controller裡提前用with方法來預加載所有的關系,例如這樣:
$pros = Province::with('cities')->get();   //或者all()
foreach($pros as $pro){
  $pro->cities();
}