优美的集合方法,如only或except,返回一个空的集合。

16

文档中,我已经使用->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: []
}

如果我从数据库获取collection,然后使用dd($myCollection);方法,它确实充满了appends,attributes等内容。这些数据在表格blade视图中显示正确。
但是如果我将->only()->except()方法应用于$myCollection,返回的collection会为空。
例如,这是collection的一部分,我只想显示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
@PaladiN 是的,我刚刚添加了它 :) 谢谢。 - Pathros
1
我之前也遇到过同样的问题,通过循环集合解决了它。 - Dev
@Dev 真的吗? 很高兴知道我不是唯一遇到这个问题的人。看看我的解决方法(我刚刚编辑了我的问题):我同时使用collect()pluck()方法,现在它按预期工作了。 - Pathros
3个回答

11

请注意,only() 只会返回应用于具有键或关联数组的指定键的项目。例如,给定一个带有键的数组:

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

但是,如果您尝试使用only()方法来处理Eloquent结果中的集合,其中包含一个没有键的集合/对象数组。

[ object, object, object ]

如果集合中有键,则它会起作用。

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

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


谢谢您的解释。我决定使用 pluck(),现在它运行良好! - Pathros

1

最有可能您想要使用 map 而不是像 OP 建议的 pluck

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;
    }
);

1

是的,我认为only()有点烦人,因为似乎没有一种简单的方法来在模型集合上使用它(这肯定是最常见的用例)。我的解决方案是将map()和only()结合起来使用,如下所示:

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

你失去了分页功能,是吗? - JEX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接