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中添加如下代码: ...
随机推荐
- Windows上为Apache配置HTTPS
Windows上为Apache配置HTTPS 转 https://www.cnblogs.com/tianzijiaozi/p/7582671.html 1. 安装OpenSSL: Windo ...
- Linux下PHP扩展pdo_mysql
1.进入PHP源码包ext/pdo目录 cd ext/pdo 2.执行/usr/local/php/bin/phpize[假设PHP的安装目录为/usr/local/php] /usr/local/p ...
- CSS入门介绍(一)
css 层叠样式表(英文名:Cascading Style Sheets),主要用于美化网页 1.css的表现形式 1.1 行内样式(内嵌样式) 写在标签内的样式,写在标签的开始部分的内部,style ...
- JavaFile I/O
Java流类图结构: 流的概念和作用: 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.及数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将抽象为各种类,方便更直观 ...
- git 强制覆盖分支
假设要用develop覆盖master分支,如下操作 git checkout master git reset --hard develop //先将本地的master分支重置成develop gi ...
- 转载Alpine基础
2018-08-06 基础镜像 FROM alpine:latest 国内可用镜像地址 官方镜像列表:http://rsync.alpinelinux.org/alpine/MIRRORS.txt 镜 ...
- HDU 6321 Dynamic Graph Matching
HDU 6321 Dynamic Graph Matching (状压DP) Problem C. Dynamic Graph Matching Time Limit: 8000/4000 MS (J ...
- BringWindowToTop完美激活窗口与置顶
void ActiveWin(IntPtr h) { IntPtr hForeWnd = GetForegroundWindow();//获取当前窗口句柄 int tIdCur = GetWindow ...
- LeetCode 50 - Pow(x, n) - [快速幂]
实现 pow(x, n) ,即计算 x 的 n 次幂函数. 示例 1: 输入: 2.00000, 10输出: 1024.00000 示例 2: 输入: 2.10000, 3输出: 9.26100 示例 ...
- Java 非静态内部类中可以定义静态变量或方法吗?
如图: 这个问题的答案是不可以 由于内部类的实例化是由外部类实例化之后加载的,如果外部类还没有实例化,这时候调用内部类的静态成员,此时内部类还没有被加载,却要开始创建静态成员,这是矛盾的,所以java ...