[Laravel 7] Custom mutators

TL; TR

Laravel 7.x에선 모델의 Property인 $casts에 커스텀된 클래스를 전달해줄 수 있다.[링크]

기존의 Mutators

Laravel 7.0의 공개 일자는 2020년 2월로 현재 얼마 남지 않은 상황에 laravel.com/doc/master에 차근차근 새로운 기능들에 대한 문서들도 업데이트 되는 것 같다.

이번에 getVarNameAttribute()setVarNameAttribute($value) 를 사용하면서 mutator에 대한 커스텀은 안될까 하여 찾아보다가 master문서에 custom mutators 항목이 추가된 것을 발견하고 곧 7.0이 릴리즈 될테니 테스트겸 시도해보았다.

Laravel 7 dev 버전에 대한 설치는
laravel new laravel7 --dev 또는
composer create-project --prefer-dist laravel/laravel:7.x-dev laravel7 으로 설치 할 수 있다.

$ cd laravel7
$ php artisan --version
Laravel Framework 7.x-dev

위와같이 artisan 명령어로 버전을 확인할 수 있다.
과거엔 welcome 템플릿에 laravel 7.0 (DEV) 🚀 라고 적혀있엇는데 아마 곧 공개를 앞으도 바뀐것같다.

++ User 테이블로 Custom mutator를 테스트 해보려고 하는데 laravel/ui 가 설치되지 않는다. 찾아보니 laravel7.x 부턴 laravel/ui에 login, register 등의 컨트롤러가 포함되어 배포되기에 laravel/ui 2.x를 설치해 줘야한다.
composer requrie laravel/ui:2.x-dev --dev

기존에 mutators의 경우 array, datetime 등의 일부만 작동을 했고 만약 커스텀하게 짜기위해선 아래와 같이 해당 모델에 get, set~~Attribute 메소드를 짜줘야했다.

// App/User

public function getNameAttribute()
{
    return "my name is {$this->name}";
}

public function setNameAttribute($value)
{
    $this->name = ucfirst($value);
}

하지만 여러 테이블에서 사용될 때 반복되고 모델에도 만약 수정이 필요할 때 모델별로 다 수정해줘야하는 번거로움이 생긴다 (trait를 써도되지만 일단넘어가자..)

이번 Laravel 7.x 에선 Illuminate\Contracts\Database\Eloquent\CastsAttributes 클래스를 사용해서 datetime, array와 같인 $casts 프로퍼티에 지정할수있다.

App\Casts\Json

<?php

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;

class Json implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  mixed  $value
     * @param  array  $attributes
     * @return array
     */
    public function get($model, $key, $value, $attributes)
    {
        return json_decode($value, true);
    }

    /**
     * Prepare the given value for storage.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @param  string  $key
     * @param  array  $value
     * @param  array  $attributes
     * @return string
     */
    public function set($model, $key, $value, $attributes)
    {
        return json_encode($value);
    }
}

App\User

<?php

namespace App;

use App\Casts\Json;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'options' => Json::class,
    ];
}

위와 같이 CastsAttributes 클래스를 받고 해당 클래스를 $casts로 전달해주면 자동으로 맵핑해준다.

지금은 casts를 따로 생성하는 artisan명령어는 없는것같지만, laravel 7이 릴리즈되면 추가되지 않을까싶다.

글의 문제가 있다면 댓글을 달아 주세요.

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.