Casting Values
Casting allows you to format input and output values appropriately.
Explicit Casting
You can explicitly cast input and/or output values to a specific type using annotations. This allows you to cast simple values to complex values, or simply transform it in some way. For example, you can cast a number to a \Brick\Money\Money
object or a timestamp to a \Carbon\CarbonImmutable
object.
Casts can act on both input and output, depending on if they implement CastsPropertySet
or CastsPropertyGet
.
Output casts are applied when calling toArray()
, or when serializing to JSON.
The following annotations are available:
Bag\Attributes\Cast
- Cast both input and output depending on whether it implementsCastsPropertySet
and/orCastsPropertyGet
Bag\Attributes\CastInput
— Only cast input (requires the caster implementsCastsPropertySet
)Bag\Attributes\CastOutput
— Only cast output (requires the caster implementsCastsPropertyGet
)
use Bag\Bag;
use Bag\Attributes\Cast;
use Bag\Casts\DateTime;
use Carbon\CarbonImmutable;
readonly class MyValue extends Bag {
public function __construct(
public string $name,
public int $age,
#[Cast(DateTime::class, format: 'Y-m-d')]
public CarbonImmutable $dateOfBirth,
) {
}
}
This will cast the dateOfBirth
property to a \Carbon\CarbonImmutable
object using the Y-m-d
format:
$value = MyValue::from([
'name' => 'Davey Shafik',
'age' => 40,
'dateOfBirth' => '1984-05-31',
]);
When you access the dateOfBirth
property directly, it will be a \Carbon\CarbonImmutable
object:
dump($value->dateOfBirth); // CarbonImmutable
However, if you call toArray()
then it will be formatted using the format you specified:
dump($value->toArray()); // ['name' => 'Davey Shafik', 'age' => 40, 'dateOfBirth' => '1984-05-31']
Available Casts
Bag supports several built-in casters, and you can create your own by implementing CastsPropertySet
and/or CastsPropertyGet
.
Automatic Casting
If no cast attribute is provided, input values are automatically cast to the correct type based on the type hint of the property when possible.
The following types are automatically cast:
- Scalar types (i.e.
int
,float
,bool
,string
) \CarbonImmutable
,\Carbon
,\DateTimeImmutable
, and\DateTime
objects (parsing the value using PHP date/time formats)Bag
objects from arrays- Laravel Collections (i.e.
collect($value)
) - BackedEnums from value (i.e.
public FooEnum $foo
will cast the valueBAR
usingFooEnum::from('BAR')
) - UnitEnums by name (i.e.
public FooEnum $foo
will cast the valueBAR
toFooEnum::BAR
) - Laravel Models from IDs (using
Model::findOrFail($value)
)
All other types will be set to the input value (which may be invalid). Input objects that match the type hint are not re-cast.
For example, given the following Bag class:
use Bag\Bag;
use Carbon\CarbonImmutable;
class MyValue extends Bag {
public function __construct(
public CarbonImmutable $dateOfBirth,
) {
}
}
When you create a new instance of MyValue
, the dateOfBirth
property will be a \Carbon\CarbonImmutable
object:
MyValue::from([
'dateOfBirth' => '1984-05-31',
]);
However, if you pass in a value like 12:34:56
, it will result in a \Carbon\CarbonImmutable
object with the current date and the time set to 12:34:56
.
WARNING
To avoid this issue, we recommend always using a DateTime
cast as shown above, setting the strictMode
parameter to true
. This allows you to specify a required input format.
When you access the dateOfBirth
property directly, it will be the \Carbon\CarbonImmutable
object.