Margus Pala Margus Pala - 4 months ago 34
PHP Question

Laravel Eloquent model id as string return wrong value in

There is OauthClient model which $client->id does not return correct value in Laravel 5.2.

"lucadegasperi/oauth2-server-laravel": "^5.1" is used that has in migration
$table->string('id', 40)->primary();

However when use $client->id in blade template then I get back "0" . Using dd($client) show correct value in id attribute.

What could be wrong?

Model output from dd()

OauthClient {#254 ▼
#connection: null
#table: null
#primaryKey: "id"
#keyType: "int"
#perPage: 15
+incrementing: true
+timestamps: true
#attributes: array:7 [▼
"id" => "wISw4JmlMQCCrMupjojcuDTK3k4hwtkb"
"secret" => "nnw3CPTzeQSIfT4KpR0d3XzWIKKoghB3"
"name" => "http://example.com"
"package" => "free"
"user_id" => 2
"created_at" => "2016-07-19 15:36:28"
"updated_at" => "2016-07-19 15:36:28"
]
#original: array:7 [▶]
#relations: []
#hidden: []
#visible: []
#appends: []
#fillable: []
#guarded: array:1 [▼
0 => "*"
]
#dates: []
#dateFormat: null
#casts: []
#touches: []
#observables: []
#with: []
#morphClass: null
+exists: true
+wasRecentlyCreated: false
}


Table structure from "show create table oauth_clients"

CREATE TABLE `oauth_clients` (
`id` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`secret` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`package` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `oauth_clients_id_secret_unique` (`id`,`secret`),
KEY `oauth_clients_user_id_foreign` (`user_id`),
CONSTRAINT `oauth_clients_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Answer

This is because by default the primary key is casted as int unless explicitly stated otherwise.

(int) "wISw4JmlMQCCrMupjojcuDTK3k4hwtkb" == 0

The value still exists as string, but if you use the $model->id it will go through magic __get() method defined in Illuminate\Database\Eloquent\Model class.

I'm not going to argue against using id field as string, but if you do and also want to get the string value using $model->id, you'll have to cast it as string in you model definition. There is a protected $casts array you can use for that. Just add the following to your OauthClient model:

protected $casts = ['id' => 'string'];

This will do the trick and cast the id attribute as string instead of default integer. All though I would reccommend not to use id as string in the first place.