Collections | laravel-data | Spatie

 SPATIE

  Laravel Data
===============

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-data](https://spatie.be/docs/laravel-data/v3)  As-a-data-transfer-object  Collections

 Version   v4   v3   v2   v1

 Other versions for crawler [v4](https://spatie.be/docs/laravel-data/v4) [v3](https://spatie.be/docs/laravel-data/v3) [v2](https://spatie.be/docs/laravel-data/v2) [v1](https://spatie.be/docs/laravel-data/v1)

- [ Introduction ](https://spatie.be/docs/laravel-data/v3/introduction)
- [ Support us ](https://spatie.be/docs/laravel-data/v3/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-data/v3/requirements)
- [ Installation &amp; setup ](https://spatie.be/docs/laravel-data/v3/installation-setup)
- [ Third party packages ](https://spatie.be/docs/laravel-data/v3/third-party-packages)
- [ Questions and issues ](https://spatie.be/docs/laravel-data/v3/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-data/v3/changelog)
- [ About us ](https://spatie.be/docs/laravel-data/v3/about-us)

Getting started
---------------

- [ Quickstart ](https://spatie.be/docs/laravel-data/v3/getting-started/quickstart)

As a DTO
--------

- [ Creating a data object ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/creating-a-data-object)
- [ Optional properties ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/optional-properties)
- [ Nesting ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/nesting)
- [ Collections ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/collections)
- [ Casts ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/casts)
- [ Default values ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/defaults)
- [ Computed values ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/computed)
- [ From a request ](https://spatie.be/docs/laravel-data/v3/as-a-data-transfer-object/request-to-data-object)

As a resource
-------------

- [ From data to resource ](https://spatie.be/docs/laravel-data/v3/as-a-resource/from-data-to-resource)
- [ Including and excluding properties ](https://spatie.be/docs/laravel-data/v3/as-a-resource/lazy-properties)
- [ Wrapping ](https://spatie.be/docs/laravel-data/v3/as-a-resource/wrapping)
- [ Transforming data ](https://spatie.be/docs/laravel-data/v3/as-a-resource/transformers)

Advanced usage
--------------

- [ Eloquent casting ](https://spatie.be/docs/laravel-data/v3/advanced-usage/eloquent-casting)
- [ Transforming to TypeScript ](https://spatie.be/docs/laravel-data/v3/advanced-usage/typescript)
- [ Working with dates ](https://spatie.be/docs/laravel-data/v3/advanced-usage/working-with-dates)
- [ Normalizers ](https://spatie.be/docs/laravel-data/v3/advanced-usage/normalizers)
- [ Pipeline ](https://spatie.be/docs/laravel-data/v3/advanced-usage/pipeline)
- [ Use with Inertia ](https://spatie.be/docs/laravel-data/v3/advanced-usage/use-with-inertia)
- [ Use with Livewire ](https://spatie.be/docs/laravel-data/v3/advanced-usage/use-with-livewire)
- [ Creating a cast ](https://spatie.be/docs/laravel-data/v3/advanced-usage/creating-a-cast)
- [ Creating a transformer ](https://spatie.be/docs/laravel-data/v3/advanced-usage/creating-a-transformer)
- [ Filling properties from route parameters ](https://spatie.be/docs/laravel-data/v3/advanced-usage/filling%20from-route-parameters)
- [ Creating a rule inferrer ](https://spatie.be/docs/laravel-data/v3/advanced-usage/creating-a-rule-inferrer)
- [ Internal structures ](https://spatie.be/docs/laravel-data/v3/advanced-usage/internal-structures)
- [ Custom collections ](https://spatie.be/docs/laravel-data/v3/advanced-usage/custom-collections)
- [ Mapping rules ](https://spatie.be/docs/laravel-data/v3/advanced-usage/mapping-rules)
- [ Validation attributes ](https://spatie.be/docs/laravel-data/v3/advanced-usage/validation-attributes)
- [ Performance ](https://spatie.be/docs/laravel-data/v3/advanced-usage/performance)
- [ Commands ](https://spatie.be/docs/laravel-data/v3/advanced-usage/commands)

      You are viewing the documentation for **an older version** of this package. You can check the version you are using with the following command:

 `                                    composer show spatie/laravel-data                                                                                                                                                                                                                                    `

Collections
===========

###  On this page

1. [ Creating ](#content-creating-datacollections)
2. [ Paginated collections ](#content-paginated-collections)
3. [ Typing data within your collections ](#content-typing-data-within-your-collections)

The package provides next to the `Data` class also a `DataCollection`, `PaginatedCollection` and `CursorPaginatedCollection` class. This collection can store a set of data objects, and we advise you to use it when storing a collection of data objects within a data object.

For example:

```
class AlbumData extends Data
{
    public function __construct(
        public string $title,
        #[DataCollectionOf(SongData::class)]
        public DataCollection $songs,
    ) {
    }
}
```

Using specific data collections is required for internal state management within the data object, which will become clear in the following chapters.

Creating `DataCollection`s
----------------------------------------------------------------------------------------------------------------------------------

There are a few different ways to create a `DataCollection`:

```
SongData::collection([
    ['title' => 'Never Gonna Give You Up', 'artist' => 'Rick Astley'],
    ['title' => 'Giving Up on Love', 'artist' => 'Rick Astley'],
]);
```

If you have a collection of models, you can do the following:

```
SongData::collection(Song::all());
```

It is even possible to add a collection of data objects:

```
SongData::collection([
    SongData::from(['title' => 'Never Gonna Give You Up', 'artist' => 'Rick Astley']),
    SongData::from(['title' => 'Giving Up on Love', 'artist' => 'Rick Astley']),
]);
```

A `DataCollection` just works like a regular array:

```
$collection = SongData::collection([
    SongData::from(['title' => 'Never Gonna Give You Up', 'artist' => 'Rick Astley'])
]);

// Count the amount of items in the collection
count($collection);

// Changing an item in the collection
$collection[0]->title = 'Giving Up on Love';

// Adding an item to the collection
$collection[] = SongData::from(['title' => 'Never Knew Love', 'artist' => 'Rick Astley']);

// Removing an item from the collection
unset($collection[0]);
```

It is even possible to loop over it with a foreach:

```
foreach ($songs as $song){
    echo $song->title;
}
```

Paginated collections
-----------------------------------------------------------------------------------------------------------------------

It is also possible to pass in a paginated collection:

```
SongData::collection(Song::paginate());
```

This will return a `PaginatedDataCollection` instead of a `DataCollection`.

A cursor paginated collection can also be used:

```
SongData::collection(Song::cursorPaginate());
```

This will result into a `CursorPaginatedCollection`

Typing data within your collections
-----------------------------------------------------------------------------------------------------------------------------------------------------------------

When nesting a data collection into your data object, always type the kind of data objects that will be stored within the collection:

```
class AlbumData extends Data
{
    public function __construct(
        public string $title,
        #[DataCollectionOf(SongData::class)]
        public DataCollection $songs,
    ) {
    }
}
```

Because we typed `$songs` as `SongData`, the package automatically knows it should create `SongData` objects when creating an `AlbumData` object from an array.

There are quite a few ways to type data collections:

```
// Without namespace

/** @var SongData[] */
public DataCollection $songs;

// With namespace

/** @var \App\Data\SongData[] */
public DataCollection $songs;

// As an array

/** @var array */
public DataCollection $songs;

// As a data collection

/** @var \Spatie\LaravelData\DataCollection */
public DataCollection $songs;

// With an attribute

#[DataCollectionOf(SongData::class)]
public DataCollection $songs;
```

You're free to use one of these annotations/attributes as long as you're using one of them when adding a data collection to a data object.

`DataCollection` methods
----------------------------------------------------------------------------------------------------------------------------

The `DataCollection` class implements a few of the Laravel collection methods:

- through
- map
- filter
- first
- each
- values
- where
- reduce
- sole

You can for example get the first item within a collection like this:

```
SongData::collection(Song::all())->first(); // SongData object
```
