> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/spatie/laravel-data/llms.txt
> Use this file to discover all available pages before exploring further.

# From a Model

> Create data objects from Eloquent models with support for casts, attributes, accessors, and relations.

It is possible to create a data object from a model. Let's say we have the following model:

```php theme={null}
class Artist extends Model
{
    
}
```

It has the following columns in the database:

* id
* first\_name
* last\_name
* created\_at
* updated\_at

We can create a data object from this model like this:

```php theme={null}
class ArtistData extends Data
{
    public int $id;
    public string $first_name;
    public string $last_name;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

We now can create a data object from the model like this:

```php theme={null}
$artist = ArtistData::from(Artist::find(1));
```

## Casts

A model can have casts, these casts will be called before a data object is created. Let's extend the model:

```php theme={null}
class Artist extends Model
{
    public function casts(): array
    {
       return [
            'properties' => 'array'
       ];
    }
}
```

Within the database the new column will be stored as a JSON string, but in the data object we can just use the array type:

```php theme={null}
class ArtistData extends Data
{
    public int $id;
    public string $first_name;
    public string $last_name;
    public array $properties;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

## Attributes & Accessors

Laravel allows you to define attributes on a model, these will be called before a data object is created. Let's extend the model:

```php theme={null}
class Artist extends Model
{
    protected function fullName(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->first_name . ' ' . $this->last_name,
        );
    }
}
```

We now can use the attribute in the data object:

```php theme={null}
class ArtistData extends Data
{
    public int $id;
    public string $full_name;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

<Note>
  Remember: we need to use the snake\_case version of the attribute in the data object since that's how it is stored in the model. Read on for a more elegant solution when you want to use camelCase property names in your data object.
</Note>

It is also possible to define accessors on a model which are the successor of the attributes:

```php theme={null}
class Artist extends Model
{
    public function getFullName(): Attribute
    {
        return Attribute::get(fn () => "{$this->first_name} {$this->last_name}");
    }
}
```

With the same data object we created earlier we can now use the accessor.

## Mapping Property Names

Sometimes you want to use camelCase property names in your data object, but the model uses snake\_case. You can use a `MapInputName` to map the property names:

```php theme={null}
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Mappers\SnakeCaseMapper;

class ArtistData extends Data
{
    public int $id;
    #[MapInputName(SnakeCaseMapper::class)]
    public string $fullName;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

An even more elegant solution would be to map every property within the data object:

```php theme={null}
#[MapInputName(SnakeCaseMapper::class)]
class ArtistData extends Data
{
    public int $id;
    public string $fullName;
    public CarbonImmutable $createdAt;
    public CarbonImmutable $updatedAt;
}
```

## Relations

Let's create a new model:

```php theme={null}
class Song extends Model
{
    public function artist(): BelongsTo
    {
        return $this->belongsTo(Artist::class);
    }
}
```

Which has the following columns in the database:

* id
* artist\_id
* title

We update our previous model as such:

```php theme={null}
class Artist extends Model
{
    public function songs(): HasMany
    {
        return $this->hasMany(Song::class);
    }
}
```

We can now create a data object like this:

```php theme={null}
class SongData extends Data
{
    public int $id;
    public string $title;
}
```

And update our previous data object like this:

```php theme={null}
class ArtistData extends Data
{
    public int $id;
    /** @var array<SongData>  */
    public array $songs;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

We can now create a data object with the relations like this:

```php theme={null}
$artist = ArtistData::from(Artist::with('songs')->find(1));
```

<Warning>
  When you're not loading the relations in advance, `null` will be returned for the relation.
</Warning>

### Automatic Relation Loading

It is however possible to load the relation on the fly by adding the `LoadRelation` attribute to the property:

```php theme={null}
class ArtistData extends Data
{
    public int $id;
    /** @var array<SongData>  */
    #[LoadRelation]
    public array $songs;
    public CarbonImmutable $created_at;
    public CarbonImmutable $updated_at;
}
```

Now the data object with relations can be created like this:

```php theme={null}
$artist = ArtistData::from(Artist::find(1));
```

We even eager-load the relation for performance, neat!

### Be Careful with Automatic Loading of Relations

Let's update the `SongData` class like this:

```php theme={null}
class SongData extends Data
{
    public int $id;
    public string $title;
    #[LoadRelation]
    public ArtistData $artist;
}
```

When we now create a data object like this:

```php theme={null}
$song = SongData::from(Song::find(1));
```

<Warning>
  We'll end up in an infinite loop, since the `SongData` class will try to load the `ArtistData` class, which will try to load the `SongData` class, and so on.
</Warning>

## Missing Attributes

When a model is missing attributes and `preventAccessingMissingAttributes` is enabled for a model the `MissingAttributeException` won't be thrown when creating a data object with a property that can be null or Optional.
