是一组数据,first()得到的是一个模型数据。在形式上,laravel中的每一个模型数据(record)在取出时都用PHP的stdClass进行了包装或封装。模型数据是一个stdClass,而stdClass是一个没有属性和方法的空类。创建一个匿名对象或者将一个非对象类型转换成一个对象,这样我们就可以方便的操作它,动态增删属性://实例化一个空对象$obj=newstdClass();//给动态添加属性或对象的方法$obj->name='pilishen.com';$obj->description='做全球最好的IT实战教程';那么,当取出多条数据,就会有多个stdClass时,我们如何显示或者包裹呢?是Collection,收藏的意思。所以,更进一步,在模型数据检索中,laravelfirst()取一个stdClass,而get()取多个stdclass,无非是用Collection的形式包装起来的。这里有一个Listallprovinces的类:可以看到,因为取出了多条数据,所以返回了一个Collection{}对象,里面包含了一个items[]数组(sequence)。在这个序列中,每个stdClass{}都加载了Object,也就是每个具体省份的数据。让我们再次打印first()方法获得的结果。我们可以看到first()方法直接获取了一个stdClass对象,因为没有包裹在数组中,所以可以直接获取上面的各种属性,比如据说我们可以直接调用关系(relationship)。假设我们创建一个ProvincehasManyCity:的例子,这样我们就可以使用Province::fisrt()->cities()来获取第一个省所属的所有城市。如果我们需要获取id为n的省内所有城市,可以使用Province::find(n)->cities(),其中find()方法还获取了一个特定于该ID的stdClass对象。这里要注意,关系(eloquentrelationship)的调用只能应用于特定的Model对象,也就是说,只有特定于某个Model,某个ID,或者某个stdclass对象,才能进一步调用。它所属的关系,而不是直接在一堆Model数据上调用关系,或者直接取一个大集合对象背后的关系,即Province::get()->cities()是错误的,这是相当于Collection{}->cities(),而这个Collection{}本身并没有cities()的关系属性。虽然里面的每一个省份模型项都有这个关系属性,只是隔了一层。嗯,在get()之后不能直接调用关系,或者说一般情况下不能在一堆数据上直接调用关系。那么,调用关系的正确姿势有哪些呢?可以在first()last()find()firstOrFail()findOrFail()这些ID特定的方法之后直接获取关系,比如Province::fisrt()->cities()如果你已经有got(),你也可以就是说已经有一堆数据了,所以可以遍历然后取每一个关系,比如:$pros=Province::get();//orall()foreach($prosas$pro){$pro->cities();}当然如果你想在Blade视图中使用遍历的关系数据,因为每次都有一条数据,你需要获取一次关系并执行一次查询,所以如果你在foreach中有n条数据,只需查询N次,有n条查询,加上你之前使用get()所有数据的一次查询,所以有在您的页面上总共有n+1个查询。当你的数据很多的时候,会导致页面特别慢,所以一旦意识到要在视图中获取关系属性,就需要使用Controller中的with方法提前预加载所有的关系,例如:$pros=Province::with('cities')->get();//orall()foreach($prosas$pro){$pro->cities();}这种情况下一次获取所有省份和每个省份下的城市关系,后面只执行两次场景查询,在视图中遍历时,不需要进行数据查询,性能会大大提升。许多新手抱怨laravel视图加载缓慢。我想知道他们是否检查过他们页面的查询执行状态?一个view查询太多query,改谁都慢~当然这些细节其实在我们的实战系列课程中已经讲过了。还没上车的童鞋们,还在等什么?
