Streamline Data Transformation with Laravel's Inbound-Only Custom Casts

Streamline Data Transformation with Laravel's Inbound-Only Custom Casts

Laravel's custom casting feature becomes even more powerful with inbound-only casts. These allow you to transform data as it's being set on the model, without affecting how it's retrieved. This is particularly useful for operations like hashing or encryption, where you want to modify the data before it's stored in the database.

Implementing Inbound-Only Custom Casts

To create an inbound-only custom cast, you need to implement the CastsInboundAttributes interface. Here's a basic structure:

use Illuminate\Contracts\Database\Eloquent\CastsInboundAttributes;

class Hash implements CastsInboundAttributes
{
    public function set($model, $key, $value, $attributes)
    {
        return bcrypt($value);
    }
}

Real-World Example: Secure User Management System

Let's consider a scenario where we're building a user management system with enhanced security features. We'll use inbound-only casting to automatically hash passwords and encrypt sensitive data before storing it in the database.

First, let's create our custom casts:

class HashPassword implements CastsInboundAttributes
{
    public function set($model, $key, $value, $attributes)
    {
        return bcrypt($value);
    }
}

class EncryptSensitiveData implements CastsInboundAttributes
{
    public function set($model, $key, $value, $attributes)
    {
        return encrypt($value);
    }
}

Now, let's apply these casts to our User model:

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name', 'email', 'password', 'social_security_number',
    ];

    protected $hidden = [
        'password', 'remember_token', 'social_security_number',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => HashPassword::class,
        'social_security_number' => EncryptSensitiveData::class,
    ];
}

Here's how we can use this in our application:

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8|confirmed',
            'social_security_number' => 'required|string|size:9',
        ]);

        $user = User::create($validatedData);

        return response()->json([
            'message' => 'User created successfully',
            'user' => $user,
        ]);
    }

    public function update(Request $request, User $user)
    {
        $validatedData = $request->validate([
            'name' => 'string|max:255',
            'email' => 'string|email|max:255|unique:users,email,'.$user->id,
            'password' => 'string|min:8|confirmed',
            'social_security_number' => 'string|size:9',
        ]);

        $user->update($validatedData);

        return response()->json([
            'message' => 'User updated successfully',
            'user' => $user,
        ]);
    }
}

By using inbound-only custom casts, we've created a more secure user management system with minimal effort. The password hashing and data encryption happen automatically when a user is created or updated, reducing the risk of accidentally storing sensitive data in plain text.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe