Eloquent- Serialization

Introduction

When we build JSON APIs, we will often need to convert our models and our relationships to arrays or JSON. Eloquent provides convenient methods for making these conversions, it also controls which attributes will be included in our serializations.

Serializing Models & Collections

Serializing To Arrays

If you want to convert a model and relationships of a model to an array, you will need to use the toArray method. This is a recursive method, hence all attributes and relations (including the relations of relations) are converted to arrays:

$user = App\User::with('roles')->first();
return $user->toArray();

if you wish to convert only the attributes of a model to an array, you should use the attributesToArray method:

$user = App\User::first();
return $user->attributesToArray();

you can also convert an entire collections of models to arrays:

$users = App\User::all();
return $users->toArray();

Serializing To JSON

If you want to convert a model to JSON, you have to use the toJson method. Just like toArray, the toJson method also recursive, so all the attributes and all relations will be converted to JSON. You can also specify JSON encoding options supported by PHP:

$user = App\User::find(1);
return $user->toJson();
return $user->toJson(JSON_PRETTY_PRINT);

In addition, you can cast a model or collection to a string, this will automatically call the toJson method on the model or collection:

$user = App\User::find(1);
return (string) $user;

Since models and collections are converted to JSON when they are cast to a string, you can return Eloquent objects directly from your application’s controllers or routes:

Route::get('users', function () {
    return App\User::all();
});

Relationships

Whenever an Eloquent model is converted to JSON, its loaded relationships is automatically included as attributes on the JSON object. Although Eloquent relationship methods are defined using “camel case”, the JSON attribute of a relationship will be “snake case”.

Hiding Attributes From JSON

There are times when you wish to limit the attributes, for example passwords, that will be included in your model’s array or JSON representation. To achieve this, you should add a $hidden property to your model:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * The attributes that are to be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = ['password'];
}

Alternatively, you can use the visible property to define a white-list of attributes that should be included in your model’s array and JSON representation. Any other attributes will be hidden when the model is converted to an array or JSON:

<?php
namespace App;
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 want to make some typically hidden attributes visible on a given model instance, you can use the makeViBsible method. The makeVBisible method will return the model instance for convenient method chaining:

return $user->makeVisible('attribute')->toArray();

Likewise, if you want to make some typically visible attributes hidden on a given model instance, you can use the makeHidden method.

return $user->makeHidden('attribute')->toArray();

Appending Values To JSON

Occasionally, when you cast models to an array or JSON, you may decide to add attributes that do not have a corresponding column in your database. To do this, you should first define an accessor for the value:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * Get the user's administrator flag.
     *
     * @return bool
     */
    public function getIsAdminAttribute()
    {
        return $this->attributes['admin'] == 'yes';
    }
}

After you create the accessor, the next thing is to add the attribute name to the appends property on the model. Note however, that attribute names will be typically referenced in “snake case”, even though you define the accessor using “camel case”:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * The accessors to append to the array form of the model.
     *
     * @var array
     */
    protected $appends = ['is_admin'];
}

Once you have added the attribute to the appends list, it is included in both the model’s array and JSON representations. Attributes in the appends array also respects the visible and hidden settings configured on the model.

Appending At Run Time

You can instruct a single model instance to append attributes using the append method. Or, you can use the setAppends method to override the entire array of appended properties for a given model instance:

return $user->append('is_admin')->toArray();
return $user->setAppends(['is_admin'])->toArray();

Date Serialization

Customizing The Date Format Per Attribute

You can choose to customize the serialization format of individual Eloquent date attributes by specifying the date format in the cast declaration:

protected $casts = [
    'birthday' => 'date:Y-m-d',
    'joined_at' => 'datetime:Y-m-d H:00',
];

Global Customization Via Carbon

Laravel extends the Carbon date library so as to provide convenient customization of Carbon’s JSON serialization format. If you want to customize how all Carbon dates throughout your application are serialized, you should use the Carbon::serializeUsing method. The serializeUsing method will accept a Closure which returns a string representation of the date for JSON serialization:

<?php
namespace App\Providers;
use Illuminate\Support\Carbon;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register the bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstraps any application services.
     *
     * @return void
     */
    public function boot()
    {
        Carbon::serializeUsing(function ($carbon) {
            return $carbon->format('U');
        });
    }
}

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *