Search code examples
phplaravellumen

Laravel: update the oldest token of user


I am currently working on the creation of an API using Lumen. I have, for the example, 2 tables users and users_token with the corresponding models User and UsersToken:

App\User:

<?php

namespace App;

use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
use Laravel\Lumen\Auth\Authorizable;

class User extends Model implements AuthenticatableContract, AuthorizableContract
{
    use Authenticatable, Authorizable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'email',
        'firstname',
        'password'
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = [
        'id',
        'password',
        'email_verified_at'
    ];


    public function tokens()
    {
        return $this->hasMany('App\UsersToken', 'user_id');
    }
}

App\UsersToken:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class UsersToken extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'users_token';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'user_id',
        'token',
    ];
}

The table users_token has 2 importants fields: user_id (foreign key linked with id field from users table) and token (a simple string).

In my model User, I have the method tokens that return all the tokens from the user using the hasMany() function:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function tokens()
    {
        return $this->hasMany('App\UsersToken');
    }
}

The table users_token also contains the defaults fields created_at and updated_at. So to get the oldest modified token of an user, I decide to use the oldest() and first() functions of Laravel:

$latestUserToken = $user->tokens->oldest('updated_at')->first();

So then I just have to update the value token of it and finally save() it:

$latestUserToken = $user->tokens->oldest('updated_at')->first();
$latestUserToken->token = 'test';
$latestUserToken->save();

But sadly I get this error message:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'id' in 'where clause' (SQL: update users_token set token = test, users_token.updated_at = 2020-04-06 17:34:59 where id is null)

If I make a print_r of $user->tokens->oldest('updated_at')->first() I get this:

[withCount:protected] => Array
        (
        )

    [perPage:protected] => 15
    [exists] => 1
    [wasRecentlyCreated] => 
    [attributes:protected] => Array
        (
            [user_id] => 11
            [token] => IsSdh03fKS3NCpfVmfm8XZyK1uYf2hSb3nRkojo86XRN7zdZnRqEOZe2HvXT
            [created_at] => 2020-04-05 17:18:22
            [updated_at] => 2020-04-01 17:18:22
        )

    [original:protected] => Array
        (
            [user_id] => 11
            [token] => IsSdh03fKS3NCpfVmfm8XZyK1uYf2hSb3nRkojo86XRN7zdZnRqEOZe2HvXT
            [created_at] => 2020-04-05 17:18:22
            [updated_at] => 2020-04-01 17:18:22
        )

    [changes:protected] => Array
        (
        )

    [casts:protected] => Array
        (
        )

    [classCastCache:protected] => Array
        (
        )

    [dates:protected] => Array
        (
        )

    [dateFormat:protected] => 
    [appends:protected] => Array
        (
        )

    [dispatchesEvents:protected] => Array
        (
        )

    [observables:protected] => Array
        (
        )

    [relations:protected] => Array
        (
        )

    [touches:protected] => Array
        (
        )

    [timestamps] => 1
    [hidden:protected] => Array
        (
        )

    [visible:protected] => Array
        (
        )

    [guarded:protected] => Array
        (
            [0] => *
        )

)

Have someone an idea where my error is?


Solution

  • I tried many different ways to generate the error in my workspace. The only time I could generate it is not having the id column in users_token table. And it looks like there's no id column in users_token table.

    If not defined explicitly, Eloquent will look for the field id as the primary key for any table. You can define the primary key field name on model using protected $primaryKey = 'token';. I'm assuming you want the field token as the primary key.

    But I would recommend not to use token as the primary. Use the plain old auto-increment long integer as the primary key and use token as a unique key. That will prevent any unwanted duplicate entry.

    The rest of the code looks okay.