Some of the answers here are really overthinking things, or they're subtly wrong.
The principle is simply to set the $casts property before you need it, eg. before writing or reading properties to the database.
In my case I needed to use a configured column name and cast it. Because PHP doesn't allow function calls in constant expressions, it can't be set in the class declaration, so I just declared my column/property's cast in my model's constructor.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MyModel extends Model
{
protected $casts = [
// we can't call a function in a class constant expression or
// we'll get 'Constant expression contains invalid operations'
// config('my-table.array-column.name') => 'array', // this won't work
];
public function __construct()
{
$this->casts = array_merge(
$this->casts, // we can still use $casts above if desired
[
// my column name is configured so it isn't known at
// compile-time so I have to set its cast run-time;
// the model's constructor is as good a place as any
config('my-table.array-column.name') => 'array',
]
);
parent::__construct(...func_get_args());
}
}