raphael's avatar

Model attributes are casted to strings

I've discovered that a record's attributes are casted to strings no matter what column type is chosen. For example the "id" or "company_id" attribute are strings but they are supposed to be integers. This problem doesn't show up when in development but when going live. Here is an example of how the attributes look like on the production server.

[ "id" => "10" "company_id" => "8" "name" => "Refreshing Shower Gel" "slug" => "refreshing-shower-gel" "description" => "" "active" => "0" "created_at" => "2016-03-04 05:54:52" "updated_at" => "2016-04-06 14:33:27" "deleted_at" => null "box_ratio" => "1x2" "cover_picture_id" => "40" "teaser_picture_id" => "39" "addition" => "Pure and natural freshness" ]

Do you know why this happens and how I can avoid it? As it is perfectly working locally without any usage of $casts within the eloquent model I'd prefer solutions without complicating my models.

0 likes
8 replies
spekkionu's avatar

All of the database functions return strings for their results regardless of field type. This isn't unique to Laravel but the database functions themselves.

Without adding it to $casts Laravel doesn't change anything and just uses what the database adapter gives it.

raphael's avatar

When dd'ing the product locally I get the following output:

[▼ "id" => 32 "company_id" => 1 "name" => "Stift mit Pinsel" "slug" => "stift-mit-pinsel" "description" => "

2423wrwer

" "active" => 1 "created_at" => "2016-03-14 14:04:35" "updated_at" => "2016-03-14 14:05:26" "deleted_at" => null "box_ratio" => "2x1" "cover_picture_id" => 5 "teaser_picture_id" => 4 "addition" => "" ]

As you can see, all ids and also the foreign keys are integers. This works without any $casts in the model. Is this due to the database?

spekkionu's avatar

To see exactly what Laravel has to work with you can use DB::getPodo() to get the underlying database connection.

$sth = \DB::getPdo()->query("SELECT * FROM products");
$product = $sth->fetch(\PDO::FETCH_ASSOC);
dd($product);

Eloquent defaults to using an auto-incrementing integer for the primary key so unless you set $incrementing = false on your model.

From the docs

In addition, Eloquent assumes that the primary key is an incrementing integer value, which means that by default the primary key will be cast to an int automatically. If you wish to use a non-incrementing or a non-numeric primary key you must set the public $incrementing property on your model to false.

Since foreign keys default to be the same as the primary keys from the table they point to it can assume those are integers as well.

Beyond those fields it has no idea what the field types are unless you tell it with the $casts array.

jimut's avatar

This happened to me too.

Integer fields are casted to string. But not in local machine this is only happening on the server.

PHP version is same with the exactly same code.

jimut's avatar
jimut
Best Answer
Level 1

Thanks @Snapey this worked for me.

Just changed the pdo_mysql driver to nd_pdo_mysql driver.

WadeShuler's avatar

Thanks @snapey and @jimut - This post saved me hours of banging my head... 7 years later :)

FWIW to anyone in the future: I have a Laravel 10 app on A2 Hosting (shared) with currently PHP version 8.2. I noticed my Livewire checkboxes were always checked, but locally, the issue isn't there. A dd() on the model and I noticed everything, except null, was a string. The user id, booleans, everything else.. Oddly, when I did a dd() on the value specifically, ie $user->id it was an integer. So yes, this issue still exists.

I solved it by going into cPanel and under the "Software" section, choosing "Select PHP Version". From there you can check all the extensions to enable/disable. I enabled "nd_pdo_mysql". It gave a warning about a conflict with something like "pdo_mysql" or something like that. I don't recall exactly. However, it seems to have solved the problem.

I am not sure if all cpanels now allow you to change the php version and manage extensions, or if it's just customization from A2 Hosting. It's a nice feature for a shared host.

1 like

Please or to participate in this conversation.