jan_zikmund's avatar

Casts with Route-Model binding

Hi, I am wondering what's the most convenient way to use $casts defined on model when I use automatic route-model binding. Eg.

// migration creating clients table
$table->decimal('rate', 10, 2)->unsigned();


// app/models/Client.php
protected $casts = [
	'rate' => 'float',
];

// routes/web.php
Route::get('clients/{client}', 'ClientController@show');

// app/Http/Controllers/ClientController.php
public function show(Client $client) {
    return $client;
}

In the example above, Controller returns client in JSON, but the client will still have rate passed as string. If I used it in Blade, then $client->rate would use the cast and give me my float. But for passing the resource to front-end, the cast looks somewhat useless, until I repeat myself in controller and add something like $client->rate = floatval($client->rate);

Is there any better way to apply casts automatically for these cases? I found withCasts() that is somewhat half the way and can help me when doing custom query, but I don't see anything reasonable for Route-Model binding.

Thanks

0 likes
4 replies
LaryAI's avatar
Level 58

The best way to apply casts automatically for route-model binding is to use the resolveUsing method on the route. This method allows you to specify a callback that will be called when the route is resolved. You can use this callback to apply the casts to the model before it is returned.

For example:

Route::get('clients/{client}', 'ClientController@show')->resolveUsing(function ($client) {
    $client->rate = floatval($client->rate);
    return $client;
});

This will apply the cast to the rate attribute before the model is returned.

jan_zikmund's avatar

@LaryAI wow, that was quick!!! Still, I am looking more for a way to automatically apply my casts that I have set on my model, rather than having to write the logic again on route.

1 like
tisuchi's avatar
tisuchi
Best Answer
Level 70

@jan_zikmund How about you use attribute?


    public function getRateAttribute()
    {
        return (float) $this->attributes['rate'];
    }
2 likes
jan_zikmund's avatar

@tisuchi Oh nice, that actually works! Still feels a bit like duplication of the $casts property, but at least can be defined on model rather than having to sanitise every route or controller šŸ‘ Thanks so much for a quick reply šŸ™

1 like

Please or to participate in this conversation.