【问题标题】:Eloquent collections methods such as only or except return an empty collection雄辩的集合方法,例如 only 或 except 返回一个空集合
【发布时间】:2017-06-17 17:38:23
【问题描述】:

docs,我用->only()方法测试了下面的例子

$collection = collect(['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]);

$filtered = $collection->only(['product_id', 'name']);

$filtered->all();

// ['product_id' => 1, 'name' => 'Desk']

它确实有效。

但是,当我将该方法应用于从数据库(模型)获取的集合时,

$myCollection = MyModel::orderBy('id','desc')->paginate(5);
$filtered=$myCollection->only(['id']);
        dd(filtered);

返回的集合是空的!

Collection {#199 ▼
  #items: []
}

如果我dd($myCollection);从数据库中得到的集合,它确实充满了附加、属性等东西。数据正确显示在表格刀片视图中。

但如果我将->only()->except() 应用于$myCollection 方法...返回的集合为空。

例如,这是集合的一部分,我只想显示id 属性,或者更多但不是全部:

LengthAwarePaginator {#218 ▼
  #total: 3041
  #lastPage: 609
  #items: Collection {#219 ▼
    #items: array:5 [▼
      0 => MyModel {#220 ▼
        #dates: array:1 [▶]
        #appends: array:5 [▶]
        #connection: null
        #table: null
        #primaryKey: "id"
        #keyType: "int"
        #perPage: 15
        +incrementing: true
        +timestamps: true
        #attributes: array:12 [▼
          "id" => 3041
          "date" => "2017-01-25"
          "value1" => "12"
          "value2" => "20"
          "value3" => "22"
          "value4" => "25"
          "value5" => "46"
          "value6" => "48"
          "value7" => "50"
          "value8" => "$60,000,000.00"
          "created_at" => null
          "updated_at" => null
        ]

但是当我申请->only(['id'])时,集合返回为空。

我没有分页测试过,空集合的问题还是一样,所以我认为与LengthAwarePaginator无关。

解决方法 不幸的是,我很难做到这一点:

    $filtered = collect(['id'=>$myCollection->pluck(['id']),'Value1'=>$myCollection->pluck('value1')]);
dd($filtered);

现在我得到了所需的集合,例如我只想要数据库中的两个属性或列:

Collection {#212 ▼
  #items: array:2 [▼
    "id" => Collection {#201 ▶}
    "value1" => Collection {#211 ▶}
  ]
}

为什么会这样?我错过了什么?我该如何解决?

【问题讨论】:

  • 你能告诉我们$myCollection返回什么吗?
  • @Paladin 是的,我刚刚添加了它:) 谢谢。
  • 前几天我也遇到过同样的问题,并使用循环收集来修复它。
  • @Dev 真的吗?很高兴知道我不是唯一一个遇到这个问题的人。看看我的解决方法(我刚刚编辑了我的问题):我正在使用 collect()pluck() 方法,现在它可以正常工作了。

标签: laravel collections laravel-5.3


【解决方案1】:

请注意only() 将返回带有指定键 的项目,该键应用于带有键的数组或关联数组。作为示例,它是带有键的数组

['product_id' => 1, 'name' => 'Desk', 'price' => 100, 'discount' => false]

但是,如果您测试将 only() 与来自 eloquent 结果的集合一起使用,其中包含集合/对象数组(没有键)。

[ object, object, object ]

如果集合包含键,它将起作用。

[ 'product_id' => object, 'name' => object ]

因此,在您只过滤指定键的值的情况下,我建议使用pluck()map()

【讨论】:

  • 感谢您的解释。我决定与pluck() 合作,现在一切正常!
【解决方案2】:

您很可能会想使用map,而不是像 OP 建议的那样采摘。

TL:DR 使用:

$mapped = $myCollection->map(
    function ($item, $key) {
      $item = $item->first(); //as item is a collection of models
      $new = [];
      $new['id']                 = $item->id;
      $new['birthdate']          = $item->birthdate;
      return $new;
    }
);

长版:

注意:groupBy 返回集合的集合

$mm = MyModel::get();

//$mm is a collection of Models

所以你有一个集合

$mm基本上是

[
0 => MyNamespace\MyModel,
1 => MyNamespace\MyModel,
...
]

现在我们运行groupBy()

$grouped = $mm->groupBy('birthdate');

现在我们有了一个包含模型的集合

$grouped基本上是:

[
'1982-10-10 01:01:01' => [
  0 = MyNamespace\MyModel
 ],
'1981-12-12 01:01:01' => [
  0 = MyNamespace\MyModel
 ],
...
]

所以要映射它只需运行:

$mapped = $grouped->map(
    function ($item, $key) {
      $item = $item->first(); //as item is a collection of models
      $new = [];
      $new['id']                 = $item->id;
      $new['birthdate']          = $item->birthdate;
      return $new;
    }
);

【讨论】:

    【解决方案3】:

    是的,我认为 only() 相当烦人,因为似乎没有一种简单的方法可以在模型集合上使用它(当然是最常见的用例)。我的解决方案是像这样结合 map() 和 only():

    $myCollection = MyModel::orderBy('id','desc')->paginate(5)->map(function ($item, $key) {
        return $item->only(['id', 'name']);
    });
    

    【讨论】:

    • 你正在失去分页,不是吗?
    猜你喜欢
    • 2021-06-23
    • 2014-10-08
    • 2013-09-08
    • 2015-03-04
    • 2015-08-15
    • 2020-09-08
    • 1970-01-01
    • 2020-08-04
    • 2013-09-06
    相关资源
    最近更新 更多