在 Laravel 5 集合中,如何 return 对象数组而不是数组数组?

In a Laravel 5 Collection how do you return an array of objects instead of an array of arrays?

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

$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

不仅 'items' 对象中的模型没有填充属性。

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

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

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

您的代码很好,只是您不需要对 Eloquent 查询结果调用 toArray。让我解释一下代码的作用,这样您就可以理解为什么下面是您想要的:

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

第一个语句 Foo::where('id', '>', 5)->get(); returns 一个 Illuminate\Support\Collection.

类型的值

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

在你的例子中,这意味着,即使 $modelsIlluminate\Support\Collection 类型,当你用 foreach:

遍历它时,它也会表现为一个数组
@foreach ($models as $model)
{
    {{ $model->foo }}
}

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

所以实际上您得到的是改进的模型数组。


此外,请不要担心 属性未填写,它们实际上已填写,我只是觉得您找错地方了。

如果仔细查看 var_dump,您会发现有些行以 publicprotectedprivate 开头。这些关键字意味着那些行包含 object properties. In the case of Laravel Eloquent models, the values fetched from the database are not stored directly in the properties that are named like the database columns. The values are in fact stored in a single property called attributes and are fetched using PHP's magic _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 不会总是显示您可能期望的简单数据结构。

解决了问题。我在模型中明确定义了属性。 Laravel 以特定方式使用 __get() ,这会导致传递的参数被显式定义的任何属性覆盖。

换句话说,我在部分中得到了空值,因为我传递给部分的信息被覆盖了。

根据 Docs:

$array = $collection->all();

"The all method returns the underlying array represented by the collection."