本文来自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,换谁都慢~
固然呢,这些细节其实在咱们的实战系列课程里都已经讲过了,尚未上车的童鞋,你还在等什么呢?