532 lines
12 KiB
Markdown
532 lines
12 KiB
Markdown
# Eloquent: Serialization
|
||
|
||
* Introduction
|
||
* Serializing Models and Collections
|
||
* Serializing to Arrays
|
||
* Serializing to JSON
|
||
* Hiding Attributes From JSON
|
||
* Appending Values to JSON
|
||
* Date Serialization
|
||
|
||
## Introduction
|
||
|
||
When building APIs using Laravel, you will often need to convert your models
|
||
and relationships to arrays or JSON. Eloquent includes convenient methods for
|
||
making these conversions, as well as controlling which attributes are included
|
||
in the serialized representation of your models.
|
||
|
||
For an even more robust way of handling Eloquent model and collection JSON
|
||
serialization, check out the documentation on [Eloquent API
|
||
resources](/docs/12.x/eloquent-resources).
|
||
|
||
## Serializing Models and Collections
|
||
|
||
### Serializing to Arrays
|
||
|
||
To convert a model and its loaded [relationships](/docs/12.x/eloquent-
|
||
relationships) to an array, you should use the `toArray` method. This method
|
||
is recursive, so all attributes and all relations (including the relations of
|
||
relations) will be converted to arrays:
|
||
|
||
|
||
|
||
1use App\Models\User;
|
||
|
||
2
|
||
|
||
3$user = User::with('roles')->first();
|
||
|
||
4
|
||
|
||
5return $user->toArray();
|
||
|
||
|
||
use App\Models\User;
|
||
|
||
$user = User::with('roles')->first();
|
||
|
||
return $user->toArray();
|
||
|
||
The `attributesToArray` method may be used to convert a model's attributes to
|
||
an array but not its relationships:
|
||
|
||
|
||
|
||
1$user = User::first();
|
||
|
||
2
|
||
|
||
3return $user->attributesToArray();
|
||
|
||
|
||
$user = User::first();
|
||
|
||
return $user->attributesToArray();
|
||
|
||
You may also convert entire [collections](/docs/12.x/eloquent-collections) of
|
||
models to arrays by calling the `toArray` method on the collection instance:
|
||
|
||
|
||
|
||
1$users = User::all();
|
||
|
||
2
|
||
|
||
3return $users->toArray();
|
||
|
||
|
||
$users = User::all();
|
||
|
||
return $users->toArray();
|
||
|
||
### Serializing to JSON
|
||
|
||
To convert a model to JSON, you should use the `toJson` method. Like
|
||
`toArray`, the `toJson` method is recursive, so all attributes and relations
|
||
will be converted to JSON. You may also specify any JSON encoding options that
|
||
are [supported by PHP](https://secure.php.net/manual/en/function.json-
|
||
encode.php):
|
||
|
||
|
||
|
||
1use App\Models\User;
|
||
|
||
2
|
||
|
||
3$user = User::find(1);
|
||
|
||
4
|
||
|
||
5return $user->toJson();
|
||
|
||
6
|
||
|
||
7return $user->toJson(JSON_PRETTY_PRINT);
|
||
|
||
|
||
use App\Models\User;
|
||
|
||
$user = User::find(1);
|
||
|
||
return $user->toJson();
|
||
|
||
return $user->toJson(JSON_PRETTY_PRINT);
|
||
|
||
Alternatively, you may cast a model or collection to a string, which will
|
||
automatically call the `toJson` method on the model or collection:
|
||
|
||
|
||
|
||
1return (string) User::find(1);
|
||
|
||
|
||
return (string) User::find(1);
|
||
|
||
Since models and collections are converted to JSON when cast to a string, you
|
||
can return Eloquent objects directly from your application's routes or
|
||
controllers. Laravel will automatically serialize your Eloquent models and
|
||
collections to JSON when they are returned from routes or controllers:
|
||
|
||
|
||
|
||
1Route::get('/users', function () {
|
||
|
||
2 return User::all();
|
||
|
||
3});
|
||
|
||
|
||
Route::get('/users', function () {
|
||
return User::all();
|
||
});
|
||
|
||
#### Relationships
|
||
|
||
When an Eloquent model is converted to JSON, its loaded relationships will
|
||
automatically be included as attributes on the JSON object. Also, though
|
||
Eloquent relationship methods are defined using "camel case" method names, a
|
||
relationship's JSON attribute will be "snake case".
|
||
|
||
## Hiding Attributes From JSON
|
||
|
||
Sometimes you may wish to limit the attributes, such as passwords, that are
|
||
included in your model's array or JSON representation. To do so, add a
|
||
`$hidden` property to your model. Attributes that are listed in the `$hidden`
|
||
property's array will not be included in the serialized representation of your
|
||
model:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Database\Eloquent\Model;
|
||
|
||
6
|
||
|
||
7class User extends Model
|
||
|
||
8{
|
||
|
||
9 /**
|
||
|
||
10 * The attributes that should be hidden for serialization.
|
||
|
||
11 *
|
||
|
||
12 * @var array<string>
|
||
|
||
13 */
|
||
|
||
14 protected $hidden = ['password'];
|
||
|
||
15}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
class User extends Model
|
||
{
|
||
/**
|
||
* The attributes that should be hidden for serialization.
|
||
*
|
||
* @var array<string>
|
||
*/
|
||
protected $hidden = ['password'];
|
||
}
|
||
|
||
To hide relationships, add the relationship's method name to your Eloquent
|
||
model's `$hidden` property.
|
||
|
||
Alternatively, you may use the `visible` property to define an "allow list" of
|
||
attributes that should be included in your model's array and JSON
|
||
representation. All attributes that are not present in the `$visible` array
|
||
will be hidden when the model is converted to an array or JSON:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Database\Eloquent\Model;
|
||
|
||
6
|
||
|
||
7class User extends Model
|
||
|
||
8{
|
||
|
||
9 /**
|
||
|
||
10 * The attributes that should be visible in arrays.
|
||
|
||
11 *
|
||
|
||
12 * @var array
|
||
|
||
13 */
|
||
|
||
14 protected $visible = ['first_name', 'last_name'];
|
||
|
||
15}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
class User extends Model
|
||
{
|
||
/**
|
||
* The attributes that should be visible in arrays.
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $visible = ['first_name', 'last_name'];
|
||
}
|
||
|
||
#### Temporarily Modifying Attribute Visibility
|
||
|
||
If you would like to make some typically hidden attributes visible on a given
|
||
model instance, you may use the `makeVisible` or `mergeVisible` methods. The
|
||
`makeVisible` method returns the model instance:
|
||
|
||
|
||
|
||
1return $user->makeVisible('attribute')->toArray();
|
||
|
||
2
|
||
|
||
3return $user->mergeVisible(['name', 'email'])->toArray();
|
||
|
||
|
||
return $user->makeVisible('attribute')->toArray();
|
||
|
||
return $user->mergeVisible(['name', 'email'])->toArray();
|
||
|
||
Likewise, if you would like to hide some attributes that are typically
|
||
visible, you may use the `makeHidden` or `mergeHidden` methods:
|
||
|
||
|
||
|
||
1return $user->makeHidden('attribute')->toArray();
|
||
|
||
2
|
||
|
||
3return $user->mergeHidden(['name', 'email'])->toArray();
|
||
|
||
|
||
return $user->makeHidden('attribute')->toArray();
|
||
|
||
return $user->mergeHidden(['name', 'email'])->toArray();
|
||
|
||
If you wish to temporarily override all of the visible or hidden attributes,
|
||
you may use the `setVisible` and `setHidden` methods respectively:
|
||
|
||
|
||
|
||
1return $user->setVisible(['id', 'name'])->toArray();
|
||
|
||
2
|
||
|
||
3return $user->setHidden(['email', 'password', 'remember_token'])->toArray();
|
||
|
||
|
||
return $user->setVisible(['id', 'name'])->toArray();
|
||
|
||
return $user->setHidden(['email', 'password', 'remember_token'])->toArray();
|
||
|
||
## Appending Values to JSON
|
||
|
||
Occasionally, when converting models to arrays or JSON, you may wish to add
|
||
attributes that do not have a corresponding column in your database. To do so,
|
||
first define an [accessor](/docs/12.x/eloquent-mutators) for the value:
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Database\Eloquent\Casts\Attribute;
|
||
|
||
6use Illuminate\Database\Eloquent\Model;
|
||
|
||
7
|
||
|
||
8class User extends Model
|
||
|
||
9{
|
||
|
||
10 /**
|
||
|
||
11 * Determine if the user is an administrator.
|
||
|
||
12 */
|
||
|
||
13 protected function isAdmin(): Attribute
|
||
|
||
14 {
|
||
|
||
15 return new Attribute(
|
||
|
||
16 get: fn () => 'yes',
|
||
|
||
17 );
|
||
|
||
18 }
|
||
|
||
19}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
class User extends Model
|
||
{
|
||
/**
|
||
* Determine if the user is an administrator.
|
||
*/
|
||
protected function isAdmin(): Attribute
|
||
{
|
||
return new Attribute(
|
||
get: fn () => 'yes',
|
||
);
|
||
}
|
||
}
|
||
|
||
If you would like the accessor to always be appended to your model's array and
|
||
JSON representations, you may add the attribute name to the `appends` property
|
||
of your model. Note that attribute names are typically referenced using their
|
||
"snake case" serialized representation, even though the accessor's PHP method
|
||
is defined using "camel case":
|
||
|
||
|
||
|
||
1<?php
|
||
|
||
2
|
||
|
||
3namespace App\Models;
|
||
|
||
4
|
||
|
||
5use Illuminate\Database\Eloquent\Model;
|
||
|
||
6
|
||
|
||
7class User extends Model
|
||
|
||
8{
|
||
|
||
9 /**
|
||
|
||
10 * The accessors to append to the model's array form.
|
||
|
||
11 *
|
||
|
||
12 * @var array
|
||
|
||
13 */
|
||
|
||
14 protected $appends = ['is_admin'];
|
||
|
||
15}
|
||
|
||
|
||
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
class User extends Model
|
||
{
|
||
/**
|
||
* The accessors to append to the model's array form.
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $appends = ['is_admin'];
|
||
}
|
||
|
||
Once the attribute has been added to the `appends` list, it will be included
|
||
in both the model's array and JSON representations. Attributes in the
|
||
`appends` array will also respect the `visible` and `hidden` settings
|
||
configured on the model.
|
||
|
||
#### Appending at Run Time
|
||
|
||
At runtime, you may instruct a model instance to append additional attributes
|
||
using the `append` or `mergeAppends` methods. Or, you may use the `setAppends`
|
||
method to override the entire array of appended properties for a given model
|
||
instance:
|
||
|
||
|
||
|
||
1return $user->append('is_admin')->toArray();
|
||
|
||
2
|
||
|
||
3return $user->mergeAppends(['is_admin', 'status'])->toArray();
|
||
|
||
4
|
||
|
||
5return $user->setAppends(['is_admin'])->toArray();
|
||
|
||
|
||
return $user->append('is_admin')->toArray();
|
||
|
||
return $user->mergeAppends(['is_admin', 'status'])->toArray();
|
||
|
||
return $user->setAppends(['is_admin'])->toArray();
|
||
|
||
## Date Serialization
|
||
|
||
#### Customizing the Default Date Format
|
||
|
||
You may customize the default serialization format by overriding the
|
||
`serializeDate` method. This method does not affect how your dates are
|
||
formatted for storage in the database:
|
||
|
||
|
||
|
||
1/**
|
||
|
||
2 * Prepare a date for array / JSON serialization.
|
||
|
||
3 */
|
||
|
||
4protected function serializeDate(DateTimeInterface $date): string
|
||
|
||
5{
|
||
|
||
6 return $date->format('Y-m-d');
|
||
|
||
7}
|
||
|
||
|
||
/**
|
||
* Prepare a date for array / JSON serialization.
|
||
*/
|
||
protected function serializeDate(DateTimeInterface $date): string
|
||
{
|
||
return $date->format('Y-m-d');
|
||
}
|
||
|
||
#### Customizing the Date Format per Attribute
|
||
|
||
You may customize the serialization format of individual Eloquent date
|
||
attributes by specifying the date format in the model's [cast
|
||
declarations](/docs/12.x/eloquent-mutators#attribute-casting):
|
||
|
||
|
||
|
||
1protected function casts(): array
|
||
|
||
2{
|
||
|
||
3 return [
|
||
|
||
4 'birthday' => 'date:Y-m-d',
|
||
|
||
5 'joined_at' => 'datetime:Y-m-d H:00',
|
||
|
||
6 ];
|
||
|
||
7}
|
||
|
||
|
||
protected function casts(): array
|
||
{
|
||
return [
|
||
'birthday' => 'date:Y-m-d',
|
||
'joined_at' => 'datetime:Y-m-d H:00',
|
||
];
|
||
}
|
||
|