Init
This commit is contained in:
577
output/12.x/eloquent-collections.md
Normal file
577
output/12.x/eloquent-collections.md
Normal file
@@ -0,0 +1,577 @@
|
||||
# Eloquent: Collections
|
||||
|
||||
* Introduction
|
||||
* Available Methods
|
||||
* Custom Collections
|
||||
|
||||
## Introduction
|
||||
|
||||
All Eloquent methods that return more than one model result will return
|
||||
instances of the `Illuminate\Database\Eloquent\Collection` class, including
|
||||
results retrieved via the `get` method or accessed via a relationship. The
|
||||
Eloquent collection object extends Laravel's [base
|
||||
collection](/docs/12.x/collections), so it naturally inherits dozens of
|
||||
methods used to fluently work with the underlying array of Eloquent models. Be
|
||||
sure to review the Laravel collection documentation to learn all about these
|
||||
helpful methods!
|
||||
|
||||
All collections also serve as iterators, allowing you to loop over them as if
|
||||
they were simple PHP arrays:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$users = User::where('active', 1)->get();
|
||||
|
||||
4
|
||||
|
||||
5foreach ($users as $user) {
|
||||
|
||||
6 echo $user->name;
|
||||
|
||||
7}
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$users = User::where('active', 1)->get();
|
||||
|
||||
foreach ($users as $user) {
|
||||
echo $user->name;
|
||||
}
|
||||
|
||||
However, as previously mentioned, collections are much more powerful than
|
||||
arrays and expose a variety of map / reduce operations that may be chained
|
||||
using an intuitive interface. For example, we may remove all inactive models
|
||||
and then gather the first name for each remaining user:
|
||||
|
||||
|
||||
|
||||
1$names = User::all()->reject(function (User $user) {
|
||||
|
||||
2 return $user->active === false;
|
||||
|
||||
3})->map(function (User $user) {
|
||||
|
||||
4 return $user->name;
|
||||
|
||||
5});
|
||||
|
||||
|
||||
$names = User::all()->reject(function (User $user) {
|
||||
return $user->active === false;
|
||||
})->map(function (User $user) {
|
||||
return $user->name;
|
||||
});
|
||||
|
||||
#### Eloquent Collection Conversion
|
||||
|
||||
While most Eloquent collection methods return a new instance of an Eloquent
|
||||
collection, the `collapse`, `flatten`, `flip`, `keys`, `pluck`, and `zip`
|
||||
methods return a [base collection](/docs/12.x/collections) instance. Likewise,
|
||||
if a `map` operation returns a collection that does not contain any Eloquent
|
||||
models, it will be converted to a base collection instance.
|
||||
|
||||
## Available Methods
|
||||
|
||||
All Eloquent collections extend the base [Laravel
|
||||
collection](/docs/12.x/collections#available-methods) object; therefore, they
|
||||
inherit all of the powerful methods provided by the base collection class.
|
||||
|
||||
In addition, the `Illuminate\Database\Eloquent\Collection` class provides a
|
||||
superset of methods to aid with managing your model collections. Most methods
|
||||
return `Illuminate\Database\Eloquent\Collection` instances; however, some
|
||||
methods, like `modelKeys`, return an `Illuminate\Support\Collection` instance.
|
||||
|
||||
append contains diff except find findOrFail fresh intersect load loadMissing
|
||||
modelKeys makeVisible makeHidden only partition setVisible setHidden toQuery
|
||||
unique
|
||||
|
||||
#### `append($attributes)`
|
||||
|
||||
The `append` method may be used to indicate that an attribute should be
|
||||
[appended](/docs/12.x/eloquent-serialization#appending-values-to-json) for
|
||||
every model in the collection. This method accepts an array of attributes or a
|
||||
single attribute:
|
||||
|
||||
|
||||
|
||||
1$users->append('team');
|
||||
|
||||
2
|
||||
|
||||
3$users->append(['team', 'is_admin']);
|
||||
|
||||
|
||||
$users->append('team');
|
||||
|
||||
$users->append(['team', 'is_admin']);
|
||||
|
||||
#### `contains($key, $operator = null, $value = null)`
|
||||
|
||||
The `contains` method may be used to determine if a given model instance is
|
||||
contained by the collection. This method accepts a primary key or a model
|
||||
instance:
|
||||
|
||||
|
||||
|
||||
1$users->contains(1);
|
||||
|
||||
2
|
||||
|
||||
3$users->contains(User::find(1));
|
||||
|
||||
|
||||
$users->contains(1);
|
||||
|
||||
$users->contains(User::find(1));
|
||||
|
||||
#### `diff($items)`
|
||||
|
||||
The `diff` method returns all of the models that are not present in the given
|
||||
collection:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$users = $users->diff(User::whereIn('id', [1, 2, 3])->get());
|
||||
|
||||
#### `except($keys)`
|
||||
|
||||
The `except` method returns all of the models that do not have the given
|
||||
primary keys:
|
||||
|
||||
|
||||
|
||||
1$users = $users->except([1, 2, 3]);
|
||||
|
||||
|
||||
$users = $users->except([1, 2, 3]);
|
||||
|
||||
#### `find($key)`
|
||||
|
||||
The `find` method returns the model that has a primary key matching the given
|
||||
key. If `$key` is a model instance, `find` will attempt to return a model
|
||||
matching the primary key. If `$key` is an array of keys, `find` will return
|
||||
all models which have a primary key in the given array:
|
||||
|
||||
|
||||
|
||||
1$users = User::all();
|
||||
|
||||
2
|
||||
|
||||
3$user = $users->find(1);
|
||||
|
||||
|
||||
$users = User::all();
|
||||
|
||||
$user = $users->find(1);
|
||||
|
||||
#### `findOrFail($key)`
|
||||
|
||||
The `findOrFail` method returns the model that has a primary key matching the
|
||||
given key or throws an `Illuminate\Database\Eloquent\ModelNotFoundException`
|
||||
exception if no matching model can be found in the collection:
|
||||
|
||||
|
||||
|
||||
1$users = User::all();
|
||||
|
||||
2
|
||||
|
||||
3$user = $users->findOrFail(1);
|
||||
|
||||
|
||||
$users = User::all();
|
||||
|
||||
$user = $users->findOrFail(1);
|
||||
|
||||
#### `fresh($with = [])`
|
||||
|
||||
The `fresh` method retrieves a fresh instance of each model in the collection
|
||||
from the database. In addition, any specified relationships will be eager
|
||||
loaded:
|
||||
|
||||
|
||||
|
||||
1$users = $users->fresh();
|
||||
|
||||
2
|
||||
|
||||
3$users = $users->fresh('comments');
|
||||
|
||||
|
||||
$users = $users->fresh();
|
||||
|
||||
$users = $users->fresh('comments');
|
||||
|
||||
#### `intersect($items)`
|
||||
|
||||
The `intersect` method returns all of the models that are also present in the
|
||||
given collection:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$users = $users->intersect(User::whereIn('id', [1, 2, 3])->get());
|
||||
|
||||
#### `load($relations)`
|
||||
|
||||
The `load` method eager loads the given relationships for all models in the
|
||||
collection:
|
||||
|
||||
|
||||
|
||||
1$users->load(['comments', 'posts']);
|
||||
|
||||
2
|
||||
|
||||
3$users->load('comments.author');
|
||||
|
||||
4
|
||||
|
||||
5$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
|
||||
|
||||
|
||||
$users->load(['comments', 'posts']);
|
||||
|
||||
$users->load('comments.author');
|
||||
|
||||
$users->load(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
|
||||
|
||||
#### `loadMissing($relations)`
|
||||
|
||||
The `loadMissing` method eager loads the given relationships for all models in
|
||||
the collection if the relationships are not already loaded:
|
||||
|
||||
|
||||
|
||||
1$users->loadMissing(['comments', 'posts']);
|
||||
|
||||
2
|
||||
|
||||
3$users->loadMissing('comments.author');
|
||||
|
||||
4
|
||||
|
||||
5$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
|
||||
|
||||
|
||||
$users->loadMissing(['comments', 'posts']);
|
||||
|
||||
$users->loadMissing('comments.author');
|
||||
|
||||
$users->loadMissing(['comments', 'posts' => fn ($query) => $query->where('active', 1)]);
|
||||
|
||||
#### `modelKeys()`
|
||||
|
||||
The `modelKeys` method returns the primary keys for all models in the
|
||||
collection:
|
||||
|
||||
|
||||
|
||||
1$users->modelKeys();
|
||||
|
||||
2
|
||||
|
||||
3// [1, 2, 3, 4, 5]
|
||||
|
||||
|
||||
$users->modelKeys();
|
||||
|
||||
// [1, 2, 3, 4, 5]
|
||||
|
||||
#### `makeVisible($attributes)`
|
||||
|
||||
The `makeVisible` method [makes attributes visible](/docs/12.x/eloquent-
|
||||
serialization#hiding-attributes-from-json) that are typically "hidden" on each
|
||||
model in the collection:
|
||||
|
||||
|
||||
|
||||
1$users = $users->makeVisible(['address', 'phone_number']);
|
||||
|
||||
|
||||
$users = $users->makeVisible(['address', 'phone_number']);
|
||||
|
||||
#### `makeHidden($attributes)`
|
||||
|
||||
The `makeHidden` method [hides attributes](/docs/12.x/eloquent-
|
||||
serialization#hiding-attributes-from-json) that are typically "visible" on
|
||||
each model in the collection:
|
||||
|
||||
|
||||
|
||||
1$users = $users->makeHidden(['address', 'phone_number']);
|
||||
|
||||
|
||||
$users = $users->makeHidden(['address', 'phone_number']);
|
||||
|
||||
#### `only($keys)`
|
||||
|
||||
The `only` method returns all of the models that have the given primary keys:
|
||||
|
||||
|
||||
|
||||
1$users = $users->only([1, 2, 3]);
|
||||
|
||||
|
||||
$users = $users->only([1, 2, 3]);
|
||||
|
||||
#### `partition`
|
||||
|
||||
The `partition` method returns an instance of `Illuminate\Support\Collection`
|
||||
containing `Illuminate\Database\Eloquent\Collection` collection instances:
|
||||
|
||||
|
||||
|
||||
1$partition = $users->partition(fn ($user) => $user->age > 18);
|
||||
|
||||
2
|
||||
|
||||
3dump($partition::class); // Illuminate\Support\Collection
|
||||
|
||||
4dump($partition[0]::class); // Illuminate\Database\Eloquent\Collection
|
||||
|
||||
5dump($partition[1]::class); // Illuminate\Database\Eloquent\Collection
|
||||
|
||||
|
||||
$partition = $users->partition(fn ($user) => $user->age > 18);
|
||||
|
||||
dump($partition::class); // Illuminate\Support\Collection
|
||||
dump($partition[0]::class); // Illuminate\Database\Eloquent\Collection
|
||||
dump($partition[1]::class); // Illuminate\Database\Eloquent\Collection
|
||||
|
||||
#### `setVisible($attributes)`
|
||||
|
||||
The `setVisible` method [temporarily overrides](/docs/12.x/eloquent-
|
||||
serialization#temporarily-modifying-attribute-visibility) all of the visible
|
||||
attributes on each model in the collection:
|
||||
|
||||
|
||||
|
||||
1$users = $users->setVisible(['id', 'name']);
|
||||
|
||||
|
||||
$users = $users->setVisible(['id', 'name']);
|
||||
|
||||
#### `setHidden($attributes)`
|
||||
|
||||
The `setHidden` method [temporarily overrides](/docs/12.x/eloquent-
|
||||
serialization#temporarily-modifying-attribute-visibility) all of the hidden
|
||||
attributes on each model in the collection:
|
||||
|
||||
|
||||
|
||||
1$users = $users->setHidden(['email', 'password', 'remember_token']);
|
||||
|
||||
|
||||
$users = $users->setHidden(['email', 'password', 'remember_token']);
|
||||
|
||||
#### `toQuery()`
|
||||
|
||||
The `toQuery` method returns an Eloquent query builder instance containing a
|
||||
`whereIn` constraint on the collection model's primary keys:
|
||||
|
||||
|
||||
|
||||
1use App\Models\User;
|
||||
|
||||
2
|
||||
|
||||
3$users = User::where('status', 'VIP')->get();
|
||||
|
||||
4
|
||||
|
||||
5$users->toQuery()->update([
|
||||
|
||||
6 'status' => 'Administrator',
|
||||
|
||||
7]);
|
||||
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
$users = User::where('status', 'VIP')->get();
|
||||
|
||||
$users->toQuery()->update([
|
||||
'status' => 'Administrator',
|
||||
]);
|
||||
|
||||
#### `unique($key = null, $strict = false)`
|
||||
|
||||
The `unique` method returns all of the unique models in the collection. Any
|
||||
models with the same primary key as another model in the collection are
|
||||
removed:
|
||||
|
||||
|
||||
|
||||
1$users = $users->unique();
|
||||
|
||||
|
||||
$users = $users->unique();
|
||||
|
||||
## Custom Collections
|
||||
|
||||
If you would like to use a custom `Collection` object when interacting with a
|
||||
given model, you may add the `CollectedBy` attribute to your model:
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace App\Models;
|
||||
|
||||
4
|
||||
|
||||
5use App\Support\UserCollection;
|
||||
|
||||
6use Illuminate\Database\Eloquent\Attributes\CollectedBy;
|
||||
|
||||
7use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
8
|
||||
|
||||
9#[CollectedBy(UserCollection::class)]
|
||||
|
||||
10class User extends Model
|
||||
|
||||
11{
|
||||
|
||||
12 // ...
|
||||
|
||||
13}
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Support\UserCollection;
|
||||
use Illuminate\Database\Eloquent\Attributes\CollectedBy;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
#[CollectedBy(UserCollection::class)]
|
||||
class User extends Model
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
Alternatively, you may define a `newCollection` method on your model:
|
||||
|
||||
|
||||
|
||||
1<?php
|
||||
|
||||
2
|
||||
|
||||
3namespace App\Models;
|
||||
|
||||
4
|
||||
|
||||
5use App\Support\UserCollection;
|
||||
|
||||
6use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
7use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
8
|
||||
|
||||
9class User extends Model
|
||||
|
||||
10{
|
||||
|
||||
11 /**
|
||||
|
||||
12 * Create a new Eloquent Collection instance.
|
||||
|
||||
13 *
|
||||
|
||||
14 * @param array<int, \Illuminate\Database\Eloquent\Model> $models
|
||||
|
||||
15 * @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
|
||||
|
||||
16 */
|
||||
|
||||
17 public function newCollection(array $models = []): Collection
|
||||
|
||||
18 {
|
||||
|
||||
19 $collection = new UserCollection($models);
|
||||
|
||||
20
|
||||
|
||||
21 if (Model::isAutomaticallyEagerLoadingRelationships()) {
|
||||
|
||||
22 $collection->withRelationshipAutoloading();
|
||||
|
||||
23 }
|
||||
|
||||
24
|
||||
|
||||
25 return $collection;
|
||||
|
||||
26 }
|
||||
|
||||
27}
|
||||
|
||||
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Support\UserCollection;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
/**
|
||||
* Create a new Eloquent Collection instance.
|
||||
*
|
||||
* @param array<int, \Illuminate\Database\Eloquent\Model> $models
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, \Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public function newCollection(array $models = []): Collection
|
||||
{
|
||||
$collection = new UserCollection($models);
|
||||
|
||||
if (Model::isAutomaticallyEagerLoadingRelationships()) {
|
||||
$collection->withRelationshipAutoloading();
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
}
|
||||
|
||||
Once you have defined a `newCollection` method or added the `CollectedBy`
|
||||
attribute to your model, you will receive an instance of your custom
|
||||
collection anytime Eloquent would normally return an
|
||||
`Illuminate\Database\Eloquent\Collection` instance.
|
||||
|
||||
If you would like to use a custom collection for every model in your
|
||||
application, you should define the `newCollection` method on a base model
|
||||
class that is extended by all of your application's models.
|
||||
|
||||
Reference in New Issue
Block a user