【问题标题】:In a Laravel 5 Collection how do you return an array of objects instead of an array of arrays?在 Laravel 5 集合中,如何返回对象数组而不是数组数组?
【发布时间】:2015-04-30 20:38:58
【问题描述】:

我正在使用 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

不仅“项目”对象中的模型没有填充属性。

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

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

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

【问题讨论】:

  • 不要在 $models 上调用 toArray()。
  • @Carter 我没有打电话给toArray()。如果我想要不同的结果,这只是一个可行的例子。
  • 我听不懂你想说的话。正如 Bogdan 回答的那样,只需将 Collection (模型)传递给视图就足够了;无需在查询结束时调用 toArray()。

标签: php laravel iterator laravel-5


【解决方案1】:

您的代码很好,除了您不需要在 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 是一个可以被视为数组的可迭代对象,但比数组更好,因为 if 提供了额外的方法,允许您操作集合中的项目。您可以查看Collection API 以查看可用方法的完整列表。

所以实际上你得到了一个改进的模型数组。


另外,不要担心属性没有填充,它们实际上已经填充了,我只是觉得你找错地方了。

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

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 不会总是显示您可能期望的简单数据结构。

【讨论】:

  • 这里的问题是属性返回空值。换句话说,$model-&gt;id$model-&gt;foo 将始终返回 null,如上面的 var_dump 所示。
  • 我会在一分钟内更新我的答案,解释为什么不是这样。
  • 即使我使用$Model-&gt;attributes 我仍然依赖于一个数组。我想要的是始终拥有$model-&gt;id,而不是$model['id']$model-&gt;attributes['id']。魔术吸气剂似乎没有返回所需的值。也许我从根本上误解了一些东西。
  • 可以使用$model-&gt;id。当您编写$model-&gt;id 时,模型类确定您想要列id 的值,并知道从attributes 数组中查找并返回它。它使用我在答案中引用的 PHP _get 方法来执行此操作。您的代码将按照您的需要运行,因为 Laravel 在幕后发挥了它的魔力。
  • 另外,要将数据传递给 Blade 中的部分视图,您需要将其作为数组类型的第二个参数传递,如下所示:@include('_partial', ['id' =&gt; $model-&gt;id, 'foo' =&gt; $model-&gt;foo])
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    根据Docs

    $array = $collection->all();
    

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

    【讨论】:

    • 这是对问题的正确答案。谢谢!
    • 谢谢! @ebakunin 请将此标记为正确答案
    猜你喜欢
    • 2018-12-07
    • 2020-01-05
    • 1970-01-01
    • 2019-05-18
    • 2020-07-21
    • 2020-06-29
    • 1970-01-01
    • 2016-06-21
    • 2018-07-20
    相关资源
    最近更新 更多