I’m using an Enum on my model’s AppLoanPurpose
field which stores an integer in the database. The integer then corrosponds to something, for example, 0 means "Other" and 1 means "Groceries".
When I cast my field, I’m still seeing the integer value returned rather than my string.
What am I missing?
<?php
namespace AppEnumsApplicationsGBPayday;
enum LoanPurpose: Int
{
case OTHER = 0;
case GROCERIES = 1;
public function label()
{
return match($this) {
self::OTHER => 'Other',
self::GROCERIES => 'Groceries'
};
}
}
Model
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;
use AppCastsJson;
use AppEnumsApplicationsGBPaydayLoanPurpose;
class ApplicationGBPayday extends Model
{
use HasFactory, SoftDeletes;
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'application_gb_paydays';
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = [];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'AppLoanPurpose' => LoanPurpose::class,
];
/**
* Get the model's application
*/
public function application()
{
return $this->morphOne(Application::class, 'modelable');
}
}
2
Answers
Casting is converting an attribute value into a supported data type,
You can’t just cast an attribute to your own data type, check the supported data type here
You have to create your own custom cast before you can use it, otherwise, just use an Accessor and Mutator
EDIT
enum casting is supported in PHP 8.1 or above
If you really want to use
enum
, you have to treat enum as a regular object.The above will create an instance of
LoanPurpose
containing two attributes,name
andvalue
.Calling those attributes
If you add a method to
LoanPurpose
, you still have to call that method in order to do something useful. In your setup, you just have to call thelabel
method which performs amatch
with whatever you’re matching.If you do not want to call the
name
orvalue
of the enum instance, you could use an attribute accessor likegetAppLoanPurposeAttribute
and do just that.Just remember that you will have lost any usefulness an enum has to offer because
ApplicationGBPayday::AppLoanPurpose
will never return aLoanPurpose
instance.So the following would not be possible
As stated in @silver’s answer, you can also use the
CastAttribute
interface, or entirely create an instance ofAttribute
and return that instead, which I think would be much easier.update
So reading all the comments you made, the attribute
AppLoanPurpose
for modelApplicationGBPayday
can be used as follow as specified in the example given in your question.If you’re not already using it, I can really advice using
tinker
with laravel-web-tinker from spatie. It gives you a lot of space to test around.