laravelphp-8

Can I use automatic casting by setting $cast property in model definition?


On laravel 10 site I use enums, defined like :

namespace App\Enums;
...    
enum PointsStatusEnum: string
{
    case STATUS_BEGIN = 'B';
    ...

    public static function getCasesArray(): array
    {
        return self::cases();
    }
}

When I define a method with this enum :

class ObjectName
{
    public static function getData(PointsStatusEnum $employeeStatus): array
    {

But When I call getData method with parameter of PointsStatusEnum with data from model field I need to use tryFrom method :

PointsStatusEnum::getData(PointsStatusEnum::tryFrom($point->status))

I wonder if there is a way make automatic casting by setting $cast property in model definition?

"laravel/framework": "^10.48.12",
"php": "8.2"

Thanks in advance!


Solution

  • I wonder if there is a way make automatic casting by setting $cast property in model definition?

    Yes, you can do that in Laravel 10 by setting $cast property in model class.

    1st-> Install bensampo/laravel-enum(check this Github link as well as packagist.org link for more info) package using this command.

    composer require bensampo/laravel-enum
    

    Then made this modification into your enum class i.e. PointsStatusEnum like this

    namespace App\Enums;
    
    use BenSampo\Enum\Enum; // import this
    
    
    enum PointsStatusEnum: string
    {
        const STATUS_BEGIN = 'B';
        const STATUS_HOLD  = 'H'; //extending as an example
        const STATUS_END   = 'E'; //extending as an example 
    
        // this is optional
        public static function getCasesArray(): array
        {
            return self::cases();
        }
    }
    

    2nd-> Then you need to import the enum-class(in your case PointsStatusEnum) into your model class and then you can specify the attribute and enum you wish to cast in your model's $casts property array like this

    use App\Enums\PointsStatusEnum;
    
    //Set the attributes that should be cast.
    protected $casts = [
        'status' => PointsStatusEnum::class,
    ];
    

    3rd-> After you have defined the cast on your model, specified attribute will be automatically cast to and from an enum when you interact with the attribute like this (just an example given below)

    //assuming `$server` is your related model instance.
    if ($server->status == PointsStatusEnum::STATUS_HOLD) {
        $server->status = PointsStatusEnum::STATUS_BEGIN;
     
        $server->save();
    }
    

    For more & detailed information you can check the laravel official-docs on enum-casting.

    N.B :- If you don't want to use packages you can avoid the 1st step of the answer.