laravel Eloquent 集合方法,例如 only 或 except 返回一个空集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41971901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:14:25  来源:igfitidea点击:

Eloquent collections methods such as only or except return an empty collection

laravelcollectionslaravel-5.3

提问by Pathros

From the docs, I have tested the following example with the ->only()method

文档中,我使用->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']

and it is working indeed.

它确实有效。

However, when I apply that method to a collection I get from the database (Model),

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

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

the collection returned is empty!

返回的集合是空的!

Collection {#199 ▼
  #items: []
}

If I dd($myCollection);the collection gotten from the database, it is indeed full of the appends, attributes, and so on stuff. The data appears correctly in the table blade view.

如果我dd($myCollection);从数据库中获取集合,它确实充满了追加、属性等内容。数据正确显示在表刀片视图中。

But if I apply either the ->only()or ->except()to $myCollectionmethods ... the returned collection is empty.

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

For example, this is the piece of the collection, where I only want to show the idattribute, for example, or some more but not all:

例如,这是集合的一部分,我只想显示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" => ",000,000.00"
          "created_at" => null
          "updated_at" => null
        ]

But when I apply ->only(['id']), the collection is returned empty.

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

I have tested it without the paginate and the problem of the empty collection is still the same, so I don't think it has to do with the LengthAwarePaginator.

我已经在没有分页的情况下对其进行了测试,并且空集合的问题仍然相同,因此我认为这与LengthAwarePaginator.

WorkaroundUnfortunately I am achieving this the hard way:

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

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

Now I am getting the desired collection where, for example I just want two attributes or columns from the database:

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

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

Why is this happening? What am I missing? How can I fix it?

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

采纳答案by xmhafiz

Take note that only()will return item(s) with the specified keywhich is applied to an array with keys or associative array. As example given, it is array with keys

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

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

However, if you test to use only()with collection from eloquent results, which contains an array of collections / objects (without key).

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

[ object, object, object ]

It will work if the collection contain keys.

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

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

Thus, in your case to filter only the values of specified keys, I suggest to use pluck()or map()

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

回答by omarjebari

Yeah i think only() is rather annoying as there doesnt seem to be an easy way to use this on collections of models (surely the most common use case). My solution is to combine map() and only() like so:

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

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

回答by Toskan

most likely you will want to use mapand not pluck like OP suggests.

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

TL:DRuse:

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

long version:

长版:

notice: groupBy returns a collection of collections

注意:groupBy 返回集合的集合

$mm = MyModel::get();

//$mm is a collection of Models

so you have a collection with

所以你有一个集合

$mmis basically

$mm基本上是

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

now we run groupBy()

现在我们跑 groupBy()

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

now we have a collection with collections containing a model(s)

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

$groupedis basically:

$grouped基本上是:

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

so to map it just run:

所以要映射它只需运行:

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