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
settoken
= test,users_token
.updated_at
= 2020-04-06 17:34:59 whereid
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?
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.