Elevate Your Laravel Models with Custom Object Casting
Laravel's Eloquent ORM offers powerful features for working with databases, and custom object casting is one of the gems that can significantly enhance your data handling. This feature allows you to transform your model attributes into complex objects, providing a clean and intuitive way to work with structured data.
Implementing Custom Object Casting
To create a custom cast, you need to implement the CastsAttributes
interface. Here's how you can do it:
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Address implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return new AddressValueObject(
$attributes['address_line_one'],
$attributes['address_line_two']
);
}
public function set($model, $key, $value, $attributes)
{
return [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
];
}
}
Real-World Example: E-commerce Customer Management
Let's consider an e-commerce platform where we need to handle customer addresses. We'll create a custom Address
cast to manage this complex data structure.
First, let's define our AddressValueObject
:
class AddressValueObject implements JsonSerializable
{
public function __construct(
public string $lineOne,
public string $lineTwo,
public string $city,
public string $state,
public string $postalCode,
public string $country
) {}
public function jsonSerialize()
{
return get_object_vars($this);
}
public function fullAddress(): string
{
return "{$this->lineOne}, {$this->lineTwo}, {$this->city}, {$this->state} {$this->postalCode}, {$this->country}";
}
}
Now, let's create our custom Address
cast:
class Address implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
return new AddressValueObject(
$attributes['address_line_one'],
$attributes['address_line_two'],
$attributes['city'],
$attributes['state'],
$attributes['postal_code'],
$attributes['country']
);
}
public function set($model, $key, $value, $attributes)
{
return [
'address_line_one' => $value->lineOne,
'address_line_two' => $value->lineTwo,
'city' => $value->city,
'state' => $value->state,
'postal_code' => $value->postalCode,
'country' => $value->country,
];
}
}
Now we can use this custom cast in our Customer
model:
class Customer extends Model
{
protected $casts = [
'address' => Address::class,
];
}
Here's how we can use this in our application:
class CustomerController extends Controller
{
public function update(Request $request, Customer $customer)
{
$customer->address = new AddressValueObject(
$request->input('address_line_one'),
$request->input('address_line_two'),
$request->input('city'),
$request->input('state'),
$request->input('postal_code'),
$request->input('country')
);
$customer->save();
return response()->json([
'message' => 'Customer updated successfully',
'full_address' => $customer->address->fullAddress(),
]);
}
public function show(Customer $customer)
{
return view('customers.show', [
'customer' => $customer,
'fullAddress' => $customer->address->fullAddress(),
]);
}
}
By leveraging custom object casting, you can create more expressive and maintainable code, especially when dealing with complex data structures. This approach is particularly useful for e-commerce platforms, CRM systems, or any application that deals with structured data that doesn't neatly fit into a single database column.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!