Laravel 5.2 - Use a String as a Custom Primary Key for Eloquent Table becomes 0

127,886

Solution 1

This was added to the upgrade documentation on Dec 29, 2015, so if you upgraded before then you probably missed it.

When fetching any attribute from the model it checks if that column should be cast as an integer, string, etc.

By default, for auto-incrementing tables, the ID is assumed to be an integer in this method:

https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L2790

So the solution is:

class UserVerification extends Model
{
    // if your key name is not 'id'
    // you can also set this to null if you don't have a primary key
    protected $primaryKey = 'your_key_name';

    public $incrementing = false;

    // In Laravel 6.0+ make sure to also set $keyType
    protected $keyType = 'string';
}

Solution 2

On the model set $incrementing to false

public $incrementing = false;

This will stop it from thinking it is an auto increment field.

Laravel Docs - Eloquent - Defining Models

Solution 3

Theres two properties on the model you need to set. The first $primaryKey to tell the model what column to expect the primary key on. The second $incrementing so it knows the primary key isn't a linear auto incrementing value.

class MyModel extends Model
{
    protected $primaryKey = 'my_column';

    public $incrementing = false;
}

For more info see the Primary Keys section in the documentation on Eloquent.

Solution 4

I was using Postman to test my Laravel API.

I received an error that stated

"SQLSTATE[42S22]: Column not found: 1054 Unknown column" because Laravel was trying to automatically create two columns "created_at" and "updated_at".

I had to enter public $timestamps = false; to my model. Then, I tested again with Postman and saw that an "id" = 0 variable was being created in my database.

I finally had to add public $incrementing false; to fix my API.

Solution 5

keep using the id


<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class UserVerification extends Model
{
    protected $table = 'user_verification';
    protected $fillable =   [
                            'id',
                            'email',
                            'verification_token'
                            ];
    //$timestamps = false;
    protected $primaryKey = 'verification_token';
}

and get the email :

$usr = User::find($id);
$token = $usr->verification_token;
$email = UserVerification::find($token);
Share:
127,886

Related videos on Youtube

Abrar Jahin
Author by

Abrar Jahin

I am Software Engineer at Relisource Inc. Working on ASP.Net Core, Android, Bootstrap, CSS3, jQuery, Angular2. Some of My other profiles are- Github Uva OnlineJudge LeetCode LinkedIn FaceBook

Updated on July 08, 2022

Comments

  • Abrar Jahin
    Abrar Jahin almost 2 years

    I am trying to use email as my table's primary key, so my eloquent code is-

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class UserVerification extends Model
    {
        protected $table = 'user_verification';
        protected $fillable =   [
                                    'email',
                                    'verification_token'
                                ];
        //$timestamps = false;
        protected $primaryKey = 'verification_token';
    }
    

    And my DB is like this-

    enter image description here

    but if I do this-

    UserVerification::where('verification_token', $token)->first();
    

    I am getting this-

    {
      "email": "[email protected]",
      "verification_token": 0,
      "created_at": "2016-01-03 22:27:44",
      "updated_at": "2016-01-03 22:27:44"
    }
    

    So, the verification token/primary key becomes 0.

    Can anyone please help?

  • andrewtweber
    andrewtweber over 8 years
    It needs to be public $incrementing to match the parent class.
  • Mubashar Abbas
    Mubashar Abbas over 7 years
    Is there a reason why $incrementing field is public instead of protected?
  • andrewtweber
    andrewtweber over 7 years
    @MubasharAbbas Well your model has to match Eloquent. Now, why does Eloquent make $incrementing public and $primaryKey protected? It's pretty arbitrary. I'm guessing $incrementing did not have getter or setter methods in earlier versions of Eloquent (it now does) and they just didn't want to make a breaking change after adding them in
  • gorodezkiy
    gorodezkiy over 6 years
    If you have no primary key (or composite keys, which are not supported by Eloquent), and you're trying to iterate such table with chunk, you can face the following error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'example.' in 'order clause'. IN this case you need to explicitly define orderBy statement, which Eloquent is trying to attach to your query with the primary key.
  • Ms. Amelia S. Greene
    Ms. Amelia S. Greene over 5 years
    Sad that these are the types of things Laravel does that prevents me from loving with all my heart. Wouldn't detecting the column type (like it does with so many other columns) make more sense?