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,集合的意思。
所以,进一步说,在model数据调取中,laravel first()取到的就是一个stdClass,而get()取到的是多个stdclass,无非是以Collection的形式包裹了起来,下面举个类子列出所有省份:
可以看到,因为是取出多条数据,所以返回的是一个Collection{}
对象,里面包含一个items[]
数组(序列),在这个序列里,装的就是每一个stdClass{}
对象,也即具体的每一个Province
数据。
我们再来打印一下first()方法获取的结果
我们可以看到first()方法得到的直接是一个stdClass对象,因为它外层没有array
包裹了,所以就可以直接在其上面获取各种属性了,比如说可以直接来调用关系(relationship)了,假设我们创建一个 Province hasMany City
的例子:
这样我们就可以使用 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
拥有这个关系属性,但那就隔着一层了。
好吧,不能在get()
后面直接调取关系,或者说不能笼统地在一堆数据上直接调取关系,那么,调取关系的正确姿势有哪些?
- 你可以在
first() last() find() firstOrFail() findOrFail()
这些具体到ID的方法后面直接取关系,比如Province::fisrt()->cities()
- 如果你已经
get()
了,也即已经有一堆数据了,那么可以遍历以后再取每一个的关系,比如:
$pros = Province::get(); //或者all()
foreach($pros as $pro){
$pro->cities();
}
- 当然,如果你是要在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();
}
这样的话,一次性地取得了所有省份以及每个省份下面的城市关系,背后只是执行了2次query,你在视图里再去遍历的时候,就不用再执行数据查询了,性能就会有较大提升。
很多小白抱怨laravel视图加载慢,不知道他们有没有查看一下自己页面的query执行情况呢?一个视图查询太多的query,换谁都慢~
laravel中get()与 first()区别、collection与stdClass的区别的更多相关文章
- 介绍Collection框架的结构;Collection 和 Collections的区别
介绍Collection框架的结构:Collection 和 Collections的区别 集合框架: Collection:List列表,Set集 Map:Hashtable,HashMap,Tre ...
- Laravel中的队列处理
Laravel中的队列处理 队列介绍 为什么要有消息队?这里先对其进行一个简单的介绍,方便还不了解的同学理解.在面向对象里,有一个很简单的概念--消息传递,而消息队列就可以在它上面扩展一下,把它说的更 ...
- Laravel中服务提供者和门面模式
在laravel中,我们可能需要用到自己添加的类时,可以建立一个文件夹专门存放类文件,也可以使用laravel的服务提供者的方式来使用. 这两者其实区别不大,主要是前者使用的话,会跟业务代码产生依赖, ...
- 统计分析中Type I Error与Type II Error的区别
统计分析中Type I Error与Type II Error的区别 在统计分析中,经常提到Type I Error和Type II Error.他们的基本概念是什么?有什么区别? 下面的表格显示 b ...
- Python中内置数据类型list,tuple,dict,set的区别和用法
Python中内置数据类型list,tuple,dict,set的区别和用法 Python语言简洁明了,可以用较少的代码实现同样的功能.这其中Python的四个内置数据类型功不可没,他们即是list, ...
- Laravel中的日志与上传
PHP中的框架众多,我自己就接触了好几个.大学那会啥也不懂啥也不会,拿了一个ThinkPHP学了.也许有好多人吐槽TP,但是个人感觉不能说哪个框架好,哪个框架不好,再不好的框架你能把源码读上一遍,框架 ...
- 程序代码中退出函数exit()与返回函数return ()的区别
程序代码中退出函数exit()与返回函数return ()的区别 exit(0):正常运行程序并退出程序: exit(1):非正常运行导致退出程序: return():返回函数,若在主函数 ...
- C#中 Request, Request.params , Request.querystring , Request.Form 区别 与联系用法
C#中 Request, Request.params , Request.querystring , Request.Form 区别 与联系用法? Request.params , Request ...
- laravel中日志为daily时如何设置最大保存天数
在laravel中,日志设置为daily时,默认保存七天的日志,超过则清除七天前的日志.可修改默认的设置,假如要保存30天的日志,则配置如下: 在配置文件config/app.php中添加如下代码: ...
随机推荐
- Servlet(九):web.xml文件和server.xml文件
Web.xml 文件使用总结:作用: 存储项目相关的配置信息,保护 Servlet.解耦一些数据对程序的依赖.使用位置: 每个 Web 项目中Tomcat 服务器中(在服务器目录 conf 目录中)区 ...
- ISP PIPLINE (附加1) Green Imbalance
1.什么是Green imbalance 芯片的Gr和Gb通道获取的能量或者是输出的数据不一致,造成这种情况的原因一方面是Gr,Gb通道的半导体制造工艺方面的差异,另一方面是microlens的存在, ...
- python yield 和 yield from用法总结
#例1. 简单输出斐波那契數列前 N 个数#缺点:该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列#要提高 fab 函数的可复用性,最好不要直接打印出数列,而是返 ...
- jQuery中height()不能精确计算的问题
jQuery中关于高度的计算有三个方法:outerHeight().innerHeight().height() outerHeight():获取元素集合中第一个元素的当前计算高度值,包括paddin ...
- (Android UI)Action Bar
Action Bar 指明用户当前所在的界面,添加多个功能性按键和下拉式选择框,以提供能多功能. 主题一:让应用具备ActionBar 可能条件一:Support Android 3.0(API 11 ...
- opencv coudn't find video stream from "XXX(文件名)"
opencv coudn't find video stream from "XXX(文件名)" 我用的是clion 解决方法: 把路径设为完整路径,如"C:/XXX&q ...
- phantomjs 中文文档
phantomjs 中文文档 转载 入门教程:转载 http://www.cnblogs.com/front-Thinking/p/4321720.html 1.介绍 简介 PhantomJS是一 ...
- Spark on Yarn with HA
Spark 可以放到yarn上面去跑,这个毫无疑问.当Yarn做了HA的时候,网上会告诉你基本Spark测不需做太多的关注修改,实际不然. 除了像spark.yarn开头的相关配置外,其中一个很重要的 ...
- Oracle 11g修改字符集
选择静默安装的安装字符集为默认的ZHS16GBK,工作中字符集为为AL32UTF8 一.登录oracle sqlplus / as sysdba shutdown immediate; STARTUP ...
- Python自学知识点----Day02
Linux基本操作命令: 命令 作用 英文释义 ls ...