在Laravel 5 Collection中,如何返回一个对象数组而不是一个数组数组?

时间:2015-02-28 01:00:56

标签: php laravel iterator laravel-5

我正在使用Laravel 5和Blade模板。在视图中,我想迭代一组Model对象,而不是一个数组数组。 如果我确实想迭代一个数组数组,我会执行以下操作,它按预期工作:

$models = Foo::where('id', '>', 5)->get();
return view('home.index', ['models' => $models->toArray()]);

但是我想要一个具有可访问属性的对象数组。如果我要跑:

$models = Foo::where('id', '>', 5)->get();
return view('home.index', ['models' => $models->all()]);

var_dump看起来像这样:

object(Illuminate\Support\Collection)[164]
  protected 'items' => 
    array (size=3)
      0 => 
        object(App\Foo)[172]
          public 'id' => null
          public 'foo' => null
          private 'created_at' => null
          private 'updated_at' => null
          protected 'connection' => null
          protected 'table' => null
          protected 'primaryKey' => string 'id' (length=2)
          protected 'perPage' => int 15
          public 'incrementing' => boolean true
          public 'timestamps' => boolean true
          protected 'attributes' => 
            array (size=4)
              'id' => int 1
              'foo' => string 'Foo!' (length=4)
              'created_at' => string '2015-02-27 15:44:09' (length=19)
              'updated_at' => null

不仅模型属于'项目'对象属性未填充。

在一个视图中我想做这样的事情:

@foreach ($models as $model)
    @include('_partial') {
        'id' => $model->id,
        'foo' => $model->foo,
    }
@endforeach

如何获取模型数组而不是模型数组的数组?

3 个答案:

答案 0 :(得分:8)

根据Docs

$array = $collection->all();

“all方法返回集合表示的底层数组。”

答案 1 :(得分:4)

您的代码很好,除非您不需要在您的Eloquent查询结果上调用toArray。让我解释代码的作用,这样你就可以理解为什么你想要的是:

$models = Foo::where('id', '>', 5)->get();
return view('home.index', ['models' => $models]);

第一个statememt Foo::where('id', '>', 5)->get();返回Illuminate\Support\Collection类型的值。

Collection类将集合元素保存在名为$items的受保护属性中(正如您从转储protected 'items' =>中看到的那样),其类型为array。该类还实现了一个名为IteratorAggregate的接口,这基本上意味着它允许使用foreach语句迭代该类型的任何变量。

在您的情况下,这意味着,即使$models的类型为Illuminate\Support\Collection,当您使用foreach覆盖它时,它也会表现为数组:

@foreach ($models as $model)
{
    {{ $model->foo }}
}

因此,简而言之Collection是一个可以被视为数组的可迭代对象,但是比数组更好,因为如果提供了允许您操作集合中的项的额外方法。您可以查看Collection API以查看可用方法的完整列表。

所以实际上你已经获得了改进的模型数组。


另外,不要担心这些属性没有被填充,它们实际上是填充的,我只是认为你在错误的地方寻找。

如果仔细查看var_dump,您会发现有些行以publicprotectedprivate开头。这些关键字表示这些行包含object properties。对于Laravel Eloquent模型,从数据库获取的值不会直接存储在名为数据库列的属性中。这些值实际上存储在一个名为attributes的属性中,并使用PHP的魔法_get获取。看看下面代码的评论:

object(Illuminate\Support\Collection)[164]
  protected 'items' => 
    array (size=3)
      0 => 
        object(App\Foo)[172]
          public 'id' => null  // <<< THE VALUES ARE
          public 'foo' => null // <<< NOT STORED HERE
          private 'created_at' => null
          private 'updated_at' => null
          protected 'connection' => null
          protected 'table' => null
          protected 'primaryKey' => string 'id' (length=2)
          protected 'perPage' => int 15
          public 'incrementing' => boolean true
          public 'timestamps' => boolean true
          protected 'attributes' => 
            array (size=4)
              'id' => int 1 // <<< THEY ARE HERE
              'foo' => string 'Foo!' (length=4) // <<< AND HERE
              'created_at' => string '2015-02-27 15:44:09' (length=19)
              'updated_at' => null

Laravel在幕后做了很多诡计,让你只用几行代码完成任务。这就是为什么var_dump不会始终显示您可能期望的简单数据结构的原因。

答案 2 :(得分:0)

找出问题所在。我明确定义了模型中的属性。 Laravel以特定的方式使用__get(),这会导致重写传递的参数,无论显式定义什么属性。

换句话说,我在partial中获取了null值,因为我传递给partial的信息被覆盖了。