Eloquent: The Magic of Mutators & Casting! ๐ฉโจ
Introduction ๐๐
Welcome, brave coders! Today weโre diving into the mystical world of Eloquent Model mutators and casting - a magical journey where data transforms with ease and elegance. Grab your wands (keyboards) and letโs get started! โจ๐งโโ๏ธ
Accessors & Mutators: The Sorcererโs Apprentices ๐งโโ๏ธ๐งโโ๏ธ
Defining an Accessor ๐
Transform data like a master alchemist! With accessors, you can return transformed data without changing the original value. Itโs like reading a spellbook but in PHP! ๐
public function getNameAttribute($value) {
return ucfirst($value);
}
Defining a Mutator ๐จ
Mutate data as if by magic! With mutators, you can change the original value before itโs saved. Itโs like enchanting an item in your favorite RPG game! ๐ก๏ธ๐งช
public function setNameAttribute($value) {
$this->attributes['name'] = strtolower($value);
}
Attribute Casting: Turning Cinders into Pumpkins ๐๐
Array and JSON Casting ๐
Transform data into arrays or JSON for easy manipulation. Itโs like learning the spell of โExpelliarmusโ on your data! ๐ค
protected $casts = [
'options' => 'array',
];
Binary Casting ๐พ
Store binary data as base64 strings. Itโs like casting a spell to turn data into invisible ink! ๐ต๏ธโโ๏ธ
protected $casts = [
'logo' => 'binary',
];
Date Casting ๐
Transform dates into a human-readable format. Itโs like casting a spell to make time stand still for a moment! โฐ
protected $dates = ['created_at', 'updated_at'];
Enum Casting ๐
Restrict values to a predefined set. Itโs like casting a spell that limits the elements of your spells! ๐งโโ๏ธ๐ช
protected $enum = [
'status' => Status::class,
];
Encrypted Casting ๐
Encrypt sensitive data for security. Itโs like casting a spell to protect your secrets! ๐ฐ
protected $encryption = 'AES-256-CBC';
protected $key = env('ENCRYPTION_KEY');
Query Time Casting ๐
Cast data as you query it. Itโs like casting a spell that filters your data on the fly! ๐
public function scopeActive($query) {
return $query->where('status', Status::ACTIVE);
}
Custom Casts: Crafting Your Own Spells ๐งโโ๏ธ๐ฎ
Value Object Casting ๐ฆ
Create custom casts for value objects. Itโs like crafting your own magic spells! ๐๏ธ๐ซ
class MoneyCast implements ShouldCastAsInterface {
// ...
}
Array / JSON Serialization ๐๐
Serialize data into arrays or JSON. Itโs like casting a spell to make your data more magical! โจ๐
public function serialize($attribute, $value) {
// ...
}
public function deserialize($attribute, $value) {
// ...
}
Inbound Casting ๐ก๏ธ๐
Transform data before itโs saved. Itโs like casting a spell to protect your data from harm! ๐ก๏ธ
public function setAttribute($attribute, $value) {
// ...
}
Cast Parameters ๐๐
Pass additional parameters to your custom casts. Itโs like adding extra ingredients to your magic potion! ๐งช๐ฅค
public function getAttribute($attribute, $value) {
// ...
}
public function setAttribute($attribute, $value) {
// ...
}
Comparing Cast Values ๐๐ฌ
Compare cast values as if they were already transformed. Itโs like comparing two spells without actually casting them! ๐งโโ๏ธ๐งโโ๏ธ
public function asArray() {
// ...
}
Castables ๐๐
Specify what data types your custom cast can handle. Itโs like setting the limitations of your magic spells! ๐งโโ๏ธ๐ฏ๏ธ
Hey There, Coders! ๐ค๐
Ever felt like your data needs a little makeover? Well, buckle up, because weโre diving into the world of Eloquent Attribute Transformations! These bad boys - Accessors, Mutators, and Attribute Casting - are your new BFFs when it comes to sprucing up model instances.
Think of them as your dataโs personal stylists who work behind the scenes, making sure everything looks fabulous before they hit the runway (aka, when you access or set values on those models).
Letโs say you want to encrypt sensitive info like your grandmaโs secret chocolate chip cookie recipe while itโs safe-kept in the database. With Laravel Encrypter (check out our Encryption docs), you can! Then, voilร , it gets automatically decrypted for you when you access that Eloquent model like a VIP backstage pass.
Or maybe youโve got a JSON string stored in your database thatโs just begging to be turned into an array. Well, who are we to deny them their dreams? Accessor and Mutator magic transforms that string into an array as soon as itโs accessed via your Eloquent model! ๐ค๐ฅ๐ค
Now, arenโt data transformations more fun with a side of sass? ๐๐ Letโs get started on making your modelsโ lives (and yours!) more fabulous than ever! ๐๐
Unveiling the Magic Mirror: Accessors and Mutators! โจ๐ช
In the mystical kingdom of Laravel, data is no longer a simple reflection in a pool. Instead, itโs a glamorous queen (or king) who may need some help to look her best before being presented to the world. Thatโs where Accessors and Mutators come into play! They are your trusted magicians, transforming data like Cinderellaโs fairy godmother ๐ฝโจ
Defining an Accessor ๐ฎ
An Accessor is a spell that lets you see a more beautiful version of your data. Itโs like those magical mirrors in fairy tales that make the ugly duckling look swan-tastic! To cast this spell, just add get before your attribute name in the getters section of your Model.
class User extends Authenticatable {
//...
public function getFullNameAttribute() {
return $this->first_name . ' ' . $this->last_name;
}
}
Now, whenever you call $user->full_name, it will return the userโs full name like a charm! ๐ฉ๐
Defining a Mutator ๐งโโ๏ธ
A Mutator is a powerful potion that gives your data a new lease of life. Imagine if the pumpkin could become a carriage just by sprinkling fairy dust! In Laravel, Mutators do exactly that. They help you change, translate, or manipulate data before itโs saved into the database.
To brew this potion, add set before your attribute name in the setters section of your Model, then cast the data as desired.
class User extends Authenticatable {
//...
public function setFirstNameAttribute($value) {
$this->attributes['first_name'] = ucfirst($value);
}
}
Now, if you try to update a userโs first name like this: $user->first_name = 'tom';, the first letter will magically transform into an uppercase T! ๐คฏ๐
So there you have it โ Accessors and Mutators are your secret weapons in making data beautiful, elegant, and perfectly suited for presentation in Laravelโs wonderful world! ๐น๐โจ
Transforming Attributes with Style!
Ahoy there, coders! Letโs talk about accessors, the superheroes of your Laravel models that step in when you need to spruce up an attribute value. To create one, just whip up a protected method on your model, naming it after the camel-cased version of your modelโs true underlying attribute or database column (if applicable).
Take our example first_name attribute, which weโre about to transform into something that would make Mr. Darcy proud! Our accessor will be called automatically by Eloquent when someone tries to grab the first_name value. But remember, all accessor and mutator methods should hint at returning the noble Illuminate\Database\Eloquent\Casts\Attribute.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the user's first name, fit for a Jane Austen novel.
*/
protected function properFirstName(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value),
);
}
}
See that? Weโve just made every userโs first name a perfect opener for a conversation. But remember, our accessor doesnโt end there! We can still manipulate the original value and return it as we please. To get your hands on this freshly-pressed first name, simply ask for it using your model instance:
use App\Models\User;
$user = User::find(1);
$firstName = $user->properFirstName; // Now, isn't that a civilized way to start a conversation?
โ ๏ธ TIP: To get these refined values sprinkled into the array or JSON versions of your glamorous model, youโd better append them! Hereโs a fancy tutorial on how to do just that.
In the grand world of Laravel, where models strut their stuff like peacocks with too much time on their hands (but who can blame them?), there comes a moment when your accessor decides itโs time to don a tuxedo and transform multiple model attributes into one dashing โValue Objectโ. Fret not, for this is as easy as teaching a newborn to pirouette!
Your get closure, ever the charming host at a fancy ball, may find itself welcoming an extra guest named $attributes. This suave gentleman will waltz into the scene automatically and gracefully present an array of all your modelโs current attributes.
Use the Address from our very own App as a date for the evening,
and Illuminate\Database\Eloquent\Casts\Attribute as the matchmaker.
/**
* Dance with the user's address.
*/
protected function address(): Attribute
{
return Attribute::make(
get: fn (mixed $value, array $attributes) => new App\Support\Address(
$attributes['address_line_one'],
$attributes['address_line_two'],
),
);
}
Now, isnโt that a swell little dance routine? Your model can now tango with multiple attributes and transform them into one glamorous value object. And who knows, maybe this newfound charm will even help them snag the โModel of the Yearโ award at the Laravel Ball! ๐คฉโจ๐๐ป๐บ๐ป
Alright, letโs dive into the whimsical world of Laravel accessor caching!
Accessor Caching: The Time-Traveling Value Buffet ๐ฒ
Ever cooked a dish only to have it change right after you served it? Not cool, right? Well, Eloquent feels your pain and has come up with a solution: time travel for values! When you return a value object from an accessor, any changes made to the time-traveling dish will automatically be synced back before the model is saved. Talk about a magical kitchen! ๐
use App\Models\User;
$user = User::find(1); // Go ahead and get that user, Captain!
// Now let's update our time-traveling dish (address)
$user->address->lineOne = 'Updated Address Line 1 Value';
$user->address->lineTwo = 'Updated Address Line 2 Value';
$user->save(); // And voila! The changes are saved in no time.
But sometimes, you may want to add a little caching for light-speed computations like strings and booleans (weโre talking about primitive values here, folks). To make that happen, you can invoke the shouldCache method when defining your accessor:
protected function hash(): Attribute
{
return Attribute::make(
get: fn (string $value) => bcrypt(gzuncompress($value)), // A complex dish recipe, I see! ๐ด
)->shouldCache(); // Add a little caching to save on those precious computing calories. ๐ฅ
}
And if youโd like to opt out of the time-traveling behavior for attributes (because letโs face it, some dishes need to be freshly cooked), you can invoke the withoutObjectCaching method when defining the attribute:
/**
* Interact with the user's address.
*/
protected function address(): Attribute
{
return Attribute::make(
get: fn (mixed $value, array $attributes) => new Address(
$attributes['address_line_one'],
$attributes['address_line_two'],
), // A freshly baked address, just the way we like it! ๐
)->withoutObjectCaching(); // No time travel for this dish, please. โณ
}
Now that youโve mastered the art of accessor caching, itโs time to move on to mutators! Stay tuned for more fun and games in our Laravel kitchen. ๐
Unleashing Attribute Sorcerers: Mutators, Your Magic Cloak for Eloquent Models! ror
In a fantasy realm where your models are the knights and attributes are the glorious steeds they ride into battle, mutators are the magical cloaks that transform those horses (or whatever medieval transportation you prefer) as they charge into combat! ๐ฅฝ๐งโโ๏ธ
To bestow this enchanting cloak upon one of your Eloquent attributes, simply cast a spell (write some code) by providing the set incantation when defining your attribute. For instance, letโs conjure up a mutator for our humble first_name attribute:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Alchemize the user's first name.
*/
protected function firstNameAlchemy(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value), // Transform the value to uppercase first letter
set: fn (string $value) => strtolower($value), // Lowercase the value as it passes through the cloak
);
}
}
Once your mutator is born, it will be automatically summoned when you attempt to bestow a new value upon the first_name attribute on the model.
use App\Models\User;
$user = User::find(1); // Find our noble knight
$user->first_name = 'SALLY'; // Attempt to set a new name, triggering the mutator's set callback
In this scenario, our set spell will be invoked with the value SALLY. The mutator will then apply its lowercase charm (the strtolower function) and return the transformed name, which will then become the knightโs new steed in the modelโs internal $attributes array.
Double, Double Toil and Trouble: Mutate Multiple Attributes ๐งโโ๏ธ๐ฎ
Should you find yourself in need of enchanting multiple attributes at once, fear not! With a wave of your wand (or some fancy code), you can cast spells upon all the horses in your knightโs stable. Just follow these simple steps:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Combine alchemy and styling for the user.
*/
protected function userTransformations(): void
{
$this->firstNameAlchemy(); // Cast the first name spell
$this->lastNameCapitalize(); // Cast the last name capitalization spell
$this->emailCamelCase(); // Cast the email camel casing spell
}
/**
* Alchemize the user's first name.
*/
protected function firstNameAlchemy(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value), // Transform the value to uppercase first letter
set: fn (string $value) => strtolower($value), // Lowercase the value as it passes through the cloak
);
}
/**
* Capitalize the user's last name.
*/
protected function lastNameCapitalize(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value), // Transform the value to uppercase first letter
set: 'set', // This mutator does not need to manipulate the value, so we just use the default set callback
);
}
/**
* Convert the user's email address to camelCase.
*/
protected function emailCamelCase(): Attribute
{
return Attribute::make(
get: fn (string $value) => str_replace('.', '', ucwords(strtolower($value))), // Replace dots and convert to camel case
set: 'set', // This mutator does not need to manipulate the value, so we just use the default set callback
);
}
}
In this example, our User model now combines three distinct spells (mutators) to transform the first_name, last_name, and email attributes all at once. When you cast these spells upon a user instance and set new values for these attributes, the respective mutators will be automatically summoned! ๐งโโ๏ธ๐ฅ
Alrighty, buckle up, because weโre about to dive into the world of Laravel attribute mutation! ๐๐
Multiple Attribute Makeover
In some cases, your swanky attribute mutator might fancy setting more than one model attribute. No problemo! Just return an array from the set closure and assign each key to a model attribute or database column itโs associated with:
use App\Support\Address;
use Illuminate\Database\Eloquent\Casts\Attribute;
/**
* Hang out at the user's address.
*/
protected function addressParty(): Attribute
{
return Attribute::make(
get: fn (mixed $value, array $attributes) => new Address(
$attributes['street'], // Because one line just isn't enough for my house number!
$attributes['city'], // And we certainly need a city to host this shindig!
),
set: fn (Address $value) => [
'street' => $value->getStreet(), // Alrighty, let's get this party started on the right street!
'city' => $value->getCity(), // Time to invite the neighbors and spread the word about our soiree!
],
);
}
Now that weโve got the fun out of our system, letโs get back to business. With this setup, your models can maintain a consistent state while handling complex data transformations. ๐๐ฅณ And remember, laughter is the best medicineโฆ unless you have a headache from typing too much PHP code! ๐๐ค
Super Power Casting for Your Models! ๐ฆธโโ๏ธ๐ฆธโโ๏ธ
Attribute casting is like giving your models superpowers, turning them into shapeshifters without even breaking a sweat! No need to create additional methods; just use the casts method on your model to convert attributes into common data types like a boss! ๐
Hereโs the lowdown on the cast types we support:
array๐ฆAsFluent::class๐ฉ (not sure who AsFluent is, but they sound fancy)AsStringable::class๐คณ (if youโre in need of a talking model)AsUri::class๐ (because who doesnโt want their models to navigate the web?)boolean๐บ๐ป (good olโ True or False)collection๐ฆ๐ฆ (for when your model needs a bag of tricks)date๐๏ธ (because even models have birthday parties)datetime๐๐ (when you want your model to tell time like a pro)immutable_date๐๐๏ธ (a date thatโs not allowed to change its clothes)immutable_datetime๐๐๐ (the same, but with time too)decimal:<precision>๐ (for models that like precision in their numbers)double๐ข (for those models that just canโt keep it simple)encrypted๐๐๏ธ (when your model has secrets to protect)encrypted:array๐ฆ๐๐๏ธ (a bag full of secrets, no less!)encrypted:collection๐ฆ๐๐๏ธ (for models that love to keep their collections under wraps)encrypted:object๐งช๐๐๏ธ (when your model has a complex, encrypted identity)float๐ข (because even models like to play with numbers sometimes)hashed๐๐จ (for models that enjoy a good password scramble)integerโ๏ธ (for those models who keep count of everything)object๐งช (when your model needs to be more than just data)real๐ข (a fancy way of saying โfloatโ)string๐ (because even models have things to write)timestampโฐ๐๏ธ (for models that need to remember everything, always)
So, letโs cast some magic on the is_admin attribute, which is stored in our database as an integer (0 or 1). Weโll turn it into a boolean value:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'is_admin' => 'boolean',
];
}
}
Now, when you access the is_admin attribute, it will magically transform into a boolean, even if it was an integer in the database:
$user = App\Models\User::find(1);
if ($user->is_admin) {
// ...
}
Need to add a temporary cast at runtime? Just use the mergeCasts method! These new cast definitions will join forces with any already defined on the model:
$user->mergeCasts([
'is_admin' => 'integer',
'options' => 'object',
]);
[!WARNING] Be careful, attributes that are
nullwill not be cast. Also, donโt define a cast (or an attribute) with the same name as a relationship or assign a cast to the modelโs primary key. That would just be weird and confusing. ๐คฏ๐คจ
Strings-a-palooza! (A.K.A Stringable Casting)
Looking to turn your model attributes into sassy, fluent Stringable objects? Well, buddy, youโve come to the right place! The Illuminate\Database\Eloquent\Casts\AsStringable cast class is just the ticket for a jamboree of stringy goodness.
<?php
namespace App\Models;
// Import all the cool kids (Cast, AsStringable)
use Illuminate\Database\Eloquent\Casts\AsStringable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* If you're casting a spell, you should know which attributes.
*
* @return array<string, string>
*/
protected function casts(): array
{
// Here's our secret sauce: AsStringable for the directory attribute
return [
'directory' => AsStringable::class,
];
}
}
And because we here at Laravel love a good party, letโs not forget about those array and JSON castings! You can find all the deets right here. But remember, with great power comes great responsibility - use it wisely, my friend! ๐ค
The Magic of JSON Transformation Crew (JTC)
Brace yourselves, data wranglers! Meet JTC - the extraordinary team that turns JSON into PHP arrays, and vice versa, with supernatural ease!
Hereโs a classic tale about our heroic cast, the array. This guy is particularly handy when dealing with database columns that are packed like sardines in serialized JSON. Imagine your database stores a JSON or TEXT field type, filled to the brim with serialized JSON goodness - adding this magical cast to that attribute will turn it into a phwoar-worthy PHP array as soon as you summon it on your Eloquent model!
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* This is the secret incantation that calls upon our cast, the array.
*/
protected function casts(): array
{
return [
'options' => 'array', // Yes, just like a magic wand!
];
}
}
Once youโve performed this mystical ritual, you can now summon the options attribute, and it will transform into a PHP array right before your eyes! But remember, with great power comes great responsibility: whenever you assign a new value to the options attribute, it gets wrapped back up in its JSON disguise for safekeeping in the database.
use App\Models\User;
$user = User::find(1);
// Gaze upon the deserialized array!
$options = $user->options;
// Add some new secrets to the mix
$options['key'] = 'value';
// Summon the transformation crew again to put the updated array back into its JSON disguise
$user->options = $options;
// Save it for posterity
$user->save();
Want a quicker way to update a single field of your JSON attribute? Give it the mass-assignment treatment and use the -> operator when invoking the update method:
$user = User::find(1);
// With a wave of your hand, make the 'options' field key take on a new value!
$user->update(['options->key' => 'value']);
Now youโre well-versed in JTCโs art of JSON transformation. Youโre officially one step closer to mastering data manipulation! ๐คฉ๐ฅ๐
Alright, folks! Letโs dive into the whimsical world of Laravel data casting, where even Emojis and Unicode characters get their time to shine! ๐๐ค
If you find yourself yearning for a smoother way to store an array attribute thatโs bursting with unescaped Unicode characters, fear not! Introducing the json:unicode cast, your new bestie in Laravel data land.
Hereโs how you can get it all set up:
/**
* Grab the attributes that deserve a fancy casting party.
*
* @return array<string, string>
*/
protected function casts()
{
return [
'options' => 'json:unicode', // It's like a magic spell for your JSON data! ๐ซ๐ฎ
];
}
Now, your Emojis and Unicode characters can join the party without having to worry about getting all tangled up in those pesky escape sequences. Happy casting! ๐ค๐
Alright, buckle up, because weโre about to dive into the magical world of Laravelโs Array Object and Collection Casting!
First off, letโs talk about the standard array cast. Itโs a swell pal for many applications, but itโs got some quirks. You see, since it returns a primitive type, direct mutation of an offset array can lead to a PHP error, much like inviting a party pooper to your shindig!
$user = User::find(1);
$user->options['key'] = $value; // ๐จ PHP Error: Call to undefined method App\Models\User::options()!
But fear not, Laravelโs got your back with the AsArrayObject cast! This bad boy transforms your JSON attribute into an ArrayObject class, allowing you to modify individual offsets without triggering a PHP errorโitโs like having a bouncer at the door of your array, only friendlier and less prone to violence.
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => AsArrayObject::class,
];
}
Next up, we have the AsCollection cast. This one turns your JSON attribute into a Laravel Collection instance. Itโs like inviting your array to a dance partyโit gets spruced up and ready to boogie!
use Illuminate\Database\Eloquent\Casts\AsCollection;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => AsCollection::class,
];
}
Now, if youโd like the AsCollection cast to instantiate a custom collection class instead of Laravelโs base collection class, you can pass the collection class name as an argument:
use App\Collections\OptionCollection;
use Illuminate\Database\Eloquent\Casts\AsCollection;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => AsCollection::using(OptionCollection::class),
];
}
If you want to map collection items into a given class, you can use the of method and the collectionโs mapInto method:
use App\ValueObjects\Option;
use Illuminate\Database\Eloquent\Casts\AsCollection;
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'options' => AsCollection::of(Option::class)
];
}
Now, when mapping collections to objects, remember these objects should implement the Illuminate\Contracts\Support\Arrayable and JsonSerializable interfaces. This helps define how their instances should be serialized into the database as JSON:
<?php
namespace App\ValueObjects;
use Illuminate\Contracts\Support\Arrayable;
use JsonSerializable;
class Option implements Arrayable, JsonSerializable
{
public string $name;
public mixed $value;
public bool $isLocked;
/**
* Create a new Option instance.
*/
public function __construct(array $data)
{
$this->name = $data['name'];
$this->value = $data['value'];
$this->isLocked = $data['is_locked'];
}
/**
* Get the instance as an array.
*
* @return array{name: string, data: string, is_locked: bool}
*/
public function toArray(): array
{
return [
'name' => $this->name,
'value' => $this->value,
'is_locked' => $this->isLocked,
];
}
/**
* Specify the data which should be serialized to JSON.
*
* @return array{name: string, data: string, is_locked: bool}
*/
public function jsonSerialize(): array
{
return $this->toArray();
}
}
And voila! Youโve just learned the art of Laravelโs Array Object and Collection Casting. Now you can party with your arrays like never before! ๐๐ผ๐บ๐ผ
Binary Buddy System
If your Eloquent model has a posh party where the guest list includes a binary type uuid or ulid column, plus the usual auto-incrementing ID column, you can call upon the AsBinaryCast bouncer to ensure seamless transformation between the value and its binary disguise:
use Illuminate\Database\Eloquent\Casts\AsBinary;
/**
* Decide who gets in through the gate.
*
* @return array<string, string>
*/
protected function getAllowedIn(): array
{
return [
'uuid' => AsBinary::uuid(),
'ulid' => AsBinary::ulid(),
];
}
With the bouncer in place, you can invite UUID or ULID guests by setting their attribute values to an object instance or a string. Our Eloquent doorman will work his magic and convert the value into its binary representation:
use Illuminate\Support\Str;
$guest->uuid = Str::uuid();
return $guest->uuid;
// "6e8cdeed-2f32-40bd-b109-1e4405be2140" - the glamorous disguise for their binary identity
Hope youโre having a swell time casting! ๐ค๐
Alright, letโs dive into the ticklish topic of Date Casting! ๐
By the way, side note: Eloquent is like that friend who always knows the right time (pun intended) and never misses a beat. It comes pre-equipped with Carbon - think of it as a swanky tuxedo over the PHP DateTime class, complete with a pocket full of useful tricks! ๐คต๏ธ
Now, if you fancy casting additional date attributes beyond the default created_at and updated_at, you can define your very own date casts within your modelโs โcastsโ method. Itโs like inviting that friend to your party โ theyโll blend right in! ๐ฅณ
Typically, dates should be cast using the โdatetimeโ or โimmutable_datetimeโ cast types. Think of it as wearing a formal suit for high-stakes events and an elegant cocktail dress for more casual gatherings (metaphorically speaking). ๐
When defining a date or datetime cast, you may also specify the dateโs format. This is useful when your model needs to look good on the dance floor โ aka serialize to an array or JSON. Hereโs the recipe for that:
/**
* Serve up the attributes that should be cast as a delectable dish.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'created_at' => 'datetime:Y-m-d', // The secret ingredient for a mouthwatering model!
];
}
When a column is cast as a date, you may set the corresponding model attribute value to various forms of time travel-worthy data. UNIX timestamp? Check. Date string (Y-m-d)? You got it. Date-time string? On it! DateTime / Carbon instance? Bring it on! The dateโs value will be correctly converted and stored in your database without a hiccup. ๐
Fancy customizing the default serialization format for all of your modelโs dates? Simply define a โserializeDateโ method on your model:
/**
* Prepare a date for a swanky dinner party (array/JSON serialization).
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d'); // The ultimate cocktail hour format!
}
To specify the format that should be used when actually storing a modelโs dates within your database, you should use the dateFormat argument on your modelโs โTableโ attribute. Itโs like setting the dress code for your database โ keep it classy! ๐คณ๐ฝ
use Illuminate\Database\Eloquent\Attributes\Table;
#[Table(dateFormat: 'U')] // Using 'U' format โ a perfect fit for timestamps!
class Flight extends Model
{
// ...
}
Now that youโve got the hang of it, go forth and cast dates with confidence! ๐
Alrighty, buckle up, because weโre about to take a wild ride through the world of Laravel date casting, serialization, and timezones! ๐๐ฐ๏ธ
By default, our date and datetime casts are like those posh British butlers who always show up in a crisp tuxedo โ they convert dates into a sleek UTC ISO-8601 date string (YYYY-MM-DDTHH:MM:SS.uuuuuuZ), no matter what timezone your application thinks itโs in (thanks to the timezone configuration option). Itโs like theyโve all been to the same etiquette school! ๐บ๏ธ
Now, you might be tempted to spice things up with a custom format for your dates, like datetime:Y-m-d H:i:s. But hold your horses, partner! When this happens, the Carbon instanceโs inner timezone (usually defined by that same timezone option) will take center stage during serialization. Just remember that columns like created_at and updated_at, being the timeless celebrities they are, always stick to UTC, no matter what your applicationโs timezone setting might be.
Now, letโs not forget about Enum casting โ itโs like having a personal stylist for your database columns! ๐คต๏ธ๐ But thatโs a whole different ball game, and we wouldnโt want to overwhelm you now, would we? ๐ฅณ
Just remember: UTC is the name of the game, and consistency is the key to making friends (and databases) in high places. Happy dating, serializing, and time-traveling! ๐๐ฐ๏ธ๐
Enchanting Enum Magic! ๐งโโ๏ธ๐ช
Step right up, data sorcerers! Laravelโs Eloquent isnโt just a wand for querying databases; itโs also a spellbook for PHP Enums! To cast your attribute values into these mystical entities, simply point your Modelโs casts method towards the attribute and enum you wish to enchant:
use App\Enums\ServerStatus;
/**
* Get the attributes that should be enchanted.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'status' => ServerStatus::class,
];
}
Once youโve bestowed this magic upon your Model, the specified attribute will be transformed into an Enum whenever you conjure it up:
if ($server->status === ServerStatus::Provisioned) {
$server->status = ServerStatus::Ready;
// Abracadabra! The server is saved with its new status. ๐ฆ
}
Remember, enchanting arrays of Enums is also possible! Hereโs a spell for that:
use App\Enums\ServerStatus;
protected function casts(): array
{
return [
'statuses' => ServerStatus::class, // <-- Array of Enums here! ๐ฆ๐ฎ
];
}
Now, whenever you access or manipulate the statuses attribute, youโll be dealing with a delightfully enchanted array of Servers. Happy querying, sorcerers! ๐โจ
Turning Your Array of Enums into a Comical Spectacle (Because Who Needs Boring, Right?)
Sometimes, your model might feel the urge to hold a riotous array of enum values in a single column, like a wild party crammed into a phone booth. To tame this chaos and bring order to the madness, Laravel offers two enchanting casts: AsEnumArrayObject and AsEnumCollection.
use App\Enums\ServerStatus;
use Illuminate\Database\Eloquent\Casts\AsEnumCollection;
/**
* Get the attributes that should be transformed into something less chaotic.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'statuses' => AsEnumCollection::of(ServerStatus::class), // Turns your array of enums into a well-behaved collection
'chaos' => AsEnumArrayObject::of(DisarrayInThePhoneBooth::class) // Because every party needs a little bit of unexpected chaos!
];
}
P.S. The DisarrayInThePhoneBooth enum is not actually part of Laravel, but it would make for a fun addition, wouldnโt it? ๐
Cryptic Capers for Columns! ๐๐
Ever had a sneaky suspicion that your data might be eavesdropped on by nosy neighbors? Fear not, Laravelโs got your back with the Encrypted Cast! Itโs like a secret decoder ring for your models, encrypting attribute values using our top-secret, built-in encryption technology.
Think of it as a superhero cape, turning plain Jane data into cryptic capers before tucking them away in your database. But like any good cape, itโs got some quirks: the encrypted text is longer than its original and its final length isnโt always predictable, so make sure your associated database column is as spacious as a grand ballroom (i.e., TEXT type or larger).
Since weโre dealing with secret squirrel business here, you wonโt be able to query or search encrypted attribute values like Sherlock Holmes would with his violin bow and magnifying glass ๐ต๏ธโโ๏ธ. But hey, if itโs good enough for James Bond, it should be good enough for your app!
Key Rotation Time! โณ๐
Now, remember that our cape isnโt just one-size-fits-all. To keep those pesky data thieves on their toes, you can rotate the encryption key like a secret agent changing hideouts! Head on over to our key rotation guide for a step-by-step on how to pull off this tricky move. ๐ต๏ธโโ๏ธ๐๐๏ธ
Alrighty, buckle up, buttercup! Youโre about to dive into the delightful world of key rotation in Laravel Land. Itโs like swapping out the secret combination to your secret garden (but with more PHP and less sunburn).
Now, you probably already know that our beloved Laravel encrypts strings using the magical key value from your appโs app.php configuration file. This key, my dear friends, is often the same as the value of your trusty APP_KEY environment variable (itโs like theyโre twins separated at birth).
But what happens when you need to change the locks on this secret garden? Well, thatโs where our graceful key rotation comes into play! Itโs not only a smoother way to rotate your keys but also a great opportunity to show off your new set of house keys to all your friends in the PHP community. (Seriously though, check out our documentation on gracefully rotating encryption keys for more details.)
Just remember: a key rotation is like a new haircut โ itโs good to keep things fresh and secure! ๐โจ๐โโ๏ธ
Time Travel with Query Casting!
Ever found yourself in a pickle, trying to make sense of raw data straight from the horseโs mouth (er, database)? Worry not, my friend! Laravelโs got your back with a feature thatโll have you feeling like Doc Brown in a DeLorean. Thatโs right, weโre talking about Query Time Casting!
Letโs take a gander at this scenario:
use App\Models\Post;
use App\Models\User;
$users = User::select([
'users.*',
'last_posted_at' => Post::selectRaw('MAX(created_at)')
->whereColumn('user_id', 'users.id')
])->get();
Now, if you squint real hard at the results, you might notice that the last_posted_at attribute is as useful as a chocolate teapot โ itโs just a string! But fret not, for we can cast this into something more akin to a Swiss timepiece with the withCasts method:
$users = User::select([
'users.*',
'last_posted_at' => Post::selectRaw('MAX(created_at)')
->whereColumn('user_id', 'users.id')
])->withCasts([
'last_posted_at' => 'datetime' // Boom! You just travelled back in time! ๐ฐ๏ธ๐
])->get();
And there you have it, my friend! Now you can make sense of those date stamps without needing a degree in chronology. Happy querying! ๐๐๐
Alrighty, Laravelโs built-in cast types are a delightful buffet of handy helpers, but sometimes you might find yourself craving your own custom flavor. Fret not! To whip up a bespoke cast, just give the trusty Artisan command a shout:
php artisan make:cast AsJson
Your new cast class will find its home in app/Casts, ready to dazzle with its culinary skills.
Every custom cast class must don the hat of the CastsAttributes interface, and this dapper suit requires two essential methods: a getter (responsible for turning database raw values into a delectable cast form) and a setter (tasked with transforming your cast creation into a tasty morsel suitable for storage). Letโs recreate the popular built-in json cast type as a custom concoction:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Database\Eloquent\Model;
class AsJson implements CastsAttributes {
// A little dance, a dash of PHP, and voila! We've got our custom cast type.
public function get(
Model $model,
string $key,
mixed $value,
array $attributes
): array {
return json_decode($value, true);
}
public function set(
Model $model,
string $key,
mixed $value,
array $attributes
): string {
return json_encode($value);
}
}
Once your custom cast type is cooked to perfection, attach it to a model attribute using its class name:
<?php
namespace App\Models;
use App\Casts\AsJson;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
// Time to set the table, and set it straight with our new custom cast.
protected function casts(): array
{
return [
'options' => AsJson::class,
];
}
}
And there you have it! Your Laravel models are now ready to serve up the freshest and most flavorful custom casts around. Bon appรฉtit! ๐ด๐ฅ๐
Alright, buckle up, Laravel cowpokes! Weโre diving into the wild world of Value Object Casting โ where your data isnโt just numbers and strings anymore, but can now be as exciting as a grizzly bear in a honey jar! ๐ป๐ฏ
Youโve already been able to cast values to primitive types like a pro, but now weโre kicking it up a notch by letting you cast them to objects! Imagine that โ casting your data into an object as effortlessly as pouring whiskey into a tumbler. ๐ฅ
Defining custom casts for objects is similar to the primitives, but thereโs one important twist if your value object involves more than one column: The set method must return an array of key-value pairs that will be used to set raw, storable values on the model. If your object only affects a single column, you can simply return the storable value like a well-dressed cowboy walking into Dodge City.
Letโs say we want to define a custom cast class that turns multiple model values into a sleek Address value object with properties lineOne and lineTwo. Weโll make some assumptions about our Address value object, which weโve named after an old-timey saloon:
<?php
namespace App\Casts;
use App\ValueObjects\Saloon as Address;
// ... (rest of the class)
Hereโs a taste of what the code inside that class might look like:
public function get(
Model $model,
string $key,
mixed $value,
array $attributes,
): Address {
return new Saloon($attributes['line_one_of_the_saloon'], $attributes['line_two_of_the_saloon']);
}
public function set(
Model $model,
string $key,
mixed $value,
array $attributes,
): array {
// ... (rest of the code)
}
Casting to value objects is a piece of cake! Any changes you make to your value object will be automatically synced back to the model before it gets saved โ just like how a cowboy might adjust his hat after dismounting from a horse. ๐ฉ
use App\Models\User;
$user = User::find(1);
$user->saloon->line_one_of_the_saloon = 'Updated Address Value';
$user->save();
[!NOTE]
When youโre planning to serialize your Eloquent models containing value objects into JSON or arrays, donโt forget to implement the Illuminate\Contracts\Support\Arrayable and JsonSerializable interfaces on the value object. Itโs as important as knowing how to rope a bronco! ๐๐
Cache-tastic Value Objects, Yโall! ๐ฅณ
In the wild world of Eloquent, when attributes turn into fancy value objects (like a chic pair of shoes or a witty one-liner), they get stashed away in the memory locker for later use. So, if you try to access that attribute again, instead of fetching it fresh off the database rack, Eloquent will hand you the very same object instance it saved earlier - talk about a fashion repeat! ๐
But what if youโre feeling a little too cachy-cachy and want to break free from this memory locker? You can do just that by declaring a public withoutObjectCaching property in your custom cast class. Just think of it as the โFree Birdโ of object caching - no more being tethered to the same instance! ๐ธ
class AsAddress implements CastsAttributes
{
public bool $withoutObjectCaching = true; // It's showtime, Charlie!
// ...
}
Now go forth and conquer those object caches with style! ๐ค๐
Array / JSON Transmogrification (aka, Turning Laravel Models into Jokes and Back)
Ah, the magical world of Laravel Eloquent models! Where data transforms into arrays and JSON like Cinderella turning into a pumpkin at midnight - but way cooler. The toArray and toJson methods are your fairy godparents here, handling the transformation, and they wonโt leave you high and dryโฆ unless youโre dealing with custom cast value objects from third-party libraries.
In such situations, adding the Illuminate\Contracts\Support\Arrayable and JsonSerializable interfaces to your object is like asking a wallflower to start a dance-off. So, we let our custom cast class take the lead! To do so, it needs to implement the Illuminate\Contracts\Database\Eloquent\SerializesCastableAttributes interface.
Think of this interface as the audition form for becoming the serenading swan of your value object transformation. Your custom cast class should impress with a serialize method, which, like a well-timed punchline, returns the serialized form of your value object:
/**
* Discover the witty one-liner of the serialized representation of the value.
*
* @param Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
*/
public function serialize(
Model $model,
string $key,
mixed $value,
array $attributes,
): string {
return (string) $value; // Transform the value into something you can laugh about
}
Now, letโs talk about inbound casting - thatโs when data from your JSON or array is transformed into an Eloquent model. Itโs like a game of Telephone, but with more coding and less childhood nostalgia. When you want to handle this transformation manually, you can create a custom cast class that implements the Illuminate\Contracts\Database\Eloquent\CastsAttributes interface. This interface demands a get method, which is like a stand-up routine for your data - it should return the transformed value from your JSON or array:
/**
* Transform the given value into a Eloquent model instance.
*
* @param mixed $value
* @param string $key
* @param array $attributes
*/
public function get(
Model $model,
string $key,
mixed $value,
array $attributes,
): \Illuminate\Database\Eloquent\Model {
// Transform the value into an Eloquent model instance here
}
And there you have it! Now youโre ready to turn data into jokes and back again. Happy coding, comedians!
The One-Way Transformers Club
Sometimes, you might find yourself in a situation where you need to create a custom cast class that only works its magic when values are being bestowed upon the model. Think of it like a butler who polishes silverware before dinner but sleeps through breakfast.
To join this exclusive club, your cast should implement the CastsInboundAttributes interface, which, in true elite fashion, requires nothing more than a swanky set method. The make:cast Artisan command can be summoned with the --inbound option to create an invitation-only cast class:
php artisan make:cast AsHash --inbound
A perfect example of a one-way cast is a โhashingโ cast. Imagine a case where we define a cast that hashes incoming values using a fancy algorithm, like a secret sauce for your data:
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;
use Illuminate\Database\Eloquent\Model;
class AsHash implements CastsInboundAttributes
{
/**
* A grand entrance for new cast members.
*/
public function __construct(protected ?string $algorithm = null) {}
/**
* Dress up before the party starts.
*
* @param array<string, mixed> $attributes
*/
public function set(Model $model, string $key, mixed $value, array $attributes): string
{
// If no algorithm is provided, we'll default to the classic bcrypt method.
if (is_null($this->algorithm)) {
return bcrypt($value);
}
// But if an algorithm is provided, we'll hash it up with style!
return hash($this->algorithm, $value);
}
}
Cast Party Time!
Ready to throw a custom cast bash in Laravel-land? When you invite a model to the dance, donโt forget to bring some party favors โ those being cast parameters! To get everyone on the same page, separate them from your class name with a colon and commas. Multiple guests are welcome, just make sure they line up politely for the entrance:
/**
* Find out who should get a makeover.
*
* @return array<string, string>
*/
protected function castParty(): array
{
return [
'secret' => 'AsHash::class'.':sha256', // Invite SHA-256 for a secret rendezvous!
];
}
Oh, and when it comes to comparing cast values, remember that theyโre just like comparing dance moves โ each one has its own groove. The constructor of the cast class will be the judge, making sure everyone gets a fair shake! ๐บ๏ธ๐
Custom Casting Magic: Making Your Models Feel Like Hogwartsโ Potion Class! ๐ซ
Ever felt like your models were missing a dash of magic? Well, grab your wand (or your keyboard) and letโs brew some custom casting potions! If you want Eloquent to understand when two values are brewed into the same magical elixir, then itโs time to whip up a custom cast class. This spellbinding concoction will allow you to control which bewitched values Eloquent considers identical and thus saves to the database when your model undergoes a transformation (or an update).
To create your very own potion brewing apparatus, youโll need to conjure up a class that implements the Illuminate\Contracts\Database\Eloquent\ComparesCastableAttributes spellbook. This ancient tome grants you the power to decide which bewitched values are considered identical and worthy of saving in your database.
The spellbook demands your custom cast class to contain a compare incantation that returns true if the given brewed potions (or values) are indeed equal:
/**
* Does this cauldron bubble or not?
*
* @param \Illuminate\Database\Eloquent\Model $model The potion-making vessel
* @param string $key The magical ingredient we're brewing
* @param mixed $firstValue The initial brew
* @param mixed $secondValue The new brew
* @return bool Is the new brew just a refill or a completely different potion?
*/
public function compare(
Model $model,
string $key,
mixed $firstValue,
mixed $secondValue
): bool {
return $firstValue === $secondValue; // If it's the same brew, it must be magic!
}
Remember to always keep your spells in order and follow the rules of potion-making etiquette. Happy casting, my friends! ๐คโจ
Magical Beans! ๐ช๐ป
Ever wished your applicationโs charm bracelets could transform into their own custom magical spells? Well, hold onto your broomsticks because we got just the potion for that! Instead of binding your model with a bewitched spell bottle, you can attach a magical bean class ๐ฑ that implements the Illuminate\Contracts\Database\Eloquent\Castable spellbook:
use Beans\MagicalAddress;
protected function brewPotions(): array
{
return [
'address' => MagicalAddress::class,
];
}
Beans that have learned the Castable spellbook must concoct a castUsing charm that reveals the name of their custom caster class responsible for brewing to and from magical potions:
<?php
namespace Beans;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Potions\AsAddress;
class MagicalAddress implements Castable
{
/**
* Discover the name of the caster class to use when brewing from / to this cast target.
*
* @param array<string, mixed> $ingredients
*/
public static function brewUsing(array $ingredients): string
{
return AsAddress::class;
}
}
When using Castable beans, you may still add ingredients to the brewPotions recipe. The ingredients will be passed to the brewUsing charm:
use Beans\MagicalAddress;
protected function brewPotions(): array
{
return [
'address' => MagicalAddress::class.':ingredient',
];
}
This section now named โAnonymous Cast Classesโ instead of โStatic Cast Classesโ for a more magical touch!
Anonymous Cast Classes ๐ป
If youโre feeling extra mystical, you can even conjure up your own anonymous cast classes on the fly! To do this, simply provide an anonymous function in the brewPotions method definition. The function will be called with the same arguments as the brewUsing charm:
use Closure;
use Beans\MagicalAddress;
protected function brewPotions(): array
{
return [
'address' => fn(Closure $ingredient) => MagicalAddress::class .':'. $ingredient(),
];
}
Alrighty then! Letโs dive into the enchanting world of Castables and Anonymous Cast Classes โ Laravelโs magical solution to making your code as stylish as a runway model and as functional as a Swiss Army Knife.
Imagine combining a value object with PHPโs secret sauce known as anonymous classes. Itโs like merging a beautiful pearl necklace with a trusty multi-tool! The result? A single, stunning, castable object complete with its very own logic for casting spells โ or in programming terms, data manipulation.
To create this sorcery, simply return an anonymous class from your value objectโs castUsing method. This mysterious, unnamed class must obey the rules set forth by the CastsAttributes interface:
<?php
namespace App\ValueObjects;
// ... Importing necessary interfaces...
class Address implements Castable
{
// ...
/**
* Call the casting covenant when we're changing from / to this cast target.
*
* @param array<string, mixed> $arguments
*/
public static function castUsing(array $arguments): CastsAttributes
{
// Abracadabra! Introducing our anonymous casting helper...
return new class implements CastsAttributes
{
// The spells this helper can perform...
public function get(
Model $model,
string $key,
mixed $value,
array $attributes,
): Address
{
// Perform a spell to create a new Address object...
return new Address(
$attributes['address_line_one'],
$attributes['address_line_two']
);
}
public function set(
Model $model,
string $key,
mixed $value,
array $attributes,
): array
{
// Cast the incoming value into a usable format and return...
return [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
];
}
};
}
}
And there you have it! With this enchanting code, you can make your Address value object dance to the tune of Laravelโs casting logic. Just remember โ practice makes perfect, so keep practicing those spells!