ismail_bourbie's avatar

Boolean cast not converting string values on save.

I’ve hit a confusing behavior with Laravel’s native boolean cast. Here’s a minimal example:

$user = User::first();
$user->test = 'on';
$user->save();

Model:

protected function casts(): array
{
    return [
        'test' => 'boolean',
    ];
}

When saving, I get:

SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'on' for column 'test'

Is this expected behavior — that the boolean cast only applies to actual booleans or numbers, not strings? Shouldn’t $model->test = 'on' go through casting before hitting the database?

0 likes
8 replies
JussiMannisto's avatar

The boolean cast is for using boolean values on the model. That means means the property returns a boolean value, and you can set a boolean value on it, even though it may be stored in an integer column in the database. It doesn't automatically convert any truthy or falsy value to boolean.

1 like
Glukinho's avatar

(string) "on" will not be casted to (bool) true or database-friendly (int) 1 unless you have your own custom cast class doing so.

String values "on", "yes", "true" are treated as boolean true only in request: https://laravel.com/docs/12.x/requests#retrieving-boolean-input-values

Also be aware that simple boolean casting (bool) "on" will lead you to wrong behavior as any non-empty string (including "off" and "false") is casted to boolean true:

(bool) "on"    === true
(bool) "yes"   === true
(bool) "true"  === true

(bool) "off"   === true
(bool) "no"    === true
(bool) "false" === true
1 like
ismail_bourbie's avatar

Right, that makes sense, but now I’m trying to understand the purpose of the boolean cast then. If I assign a real boolean (true/false), PHP or the database already handles converting it to 1 or 0 when saving. So what does the boolean cast actually do in practice?

Is it mainly just for reading converting the database integer back into a PHP boolean rather than affecting how data is written? Because if it doesn’t normalize string truthy values like 'on', 'yes', 'true', etc., then the cast seems useful only when retrieving data, not when setting it.

Glukinho's avatar

Think of it as a bridge between internal boolean true / false value in your app and database tinyint field where boolean values are actually stored.

General advice is to be as strict and explicit as possible. Since true !== 1 and false !== 0 (note I used strict comparison operator "===") you can't use raw 1 or 0 from database right in your application. I mean, you can, but explicit cast is always better and less error-prone than silent assumption that true == 1 / false == 0 (note I used loose comparison operator "==").

JussiMannisto's avatar
Level 50

Sort of. Values true and false convert to 1 and 0 when cast to int, so that would work without casting — if your DBMS stores booleans as integers.

It's still good practice to use the boolean cast when you're representing boolean values. It also ensures the property is serialized as a boolean field in JSON if it's sent to the front end, or as an API response.

1 like
Snapey's avatar

practical example from yesterday using Livewire and FluxUi

database has three 'boolean' fields. In the UI, I have three checkboxes wire modelled to the database record. The checkboxes are NOT set by 1 in the eloquent model.

Add boolean cast in the Model and the model data is now true/false not 1/0 and checkboxes now reflect the state of the Model.

1 like
havanaelon's avatar

Is it mainly just for reading converting the database integer back into a PHP boolean rather than affecting how data is written? Because if it doesn’t normalize string truthy values like 'on', 'yes', 'true', etc., then the cast seems useful only when retrieving data, not when setting it capybara clicker free.

Please or to participate in this conversation.