Laravel: 更新用户最早的token

Laravel: update the oldest token of user

我目前正在使用 Lumen 创建 API。例如,我有 2 tables usersusers_token 以及相应的模型 UserUsersToken:

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',
    ];
}

table users_token 有 2 个重要字段:user_id(与 users table 中的 id 字段链接的外键)和token(一个简单的字符串)。

在我的模型 User 中,我有方法 tokens return 来自用户使用 hasMany() 函数的所有标记:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

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

table users_token 还包含默认字段 created_atupdated_at。因此,为了获得用户最早修改的令牌,我决定使用 Laravel:

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

那么我只需要更新它的值 token 最后 save() 它:

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

但遗憾的是我收到此错误消息:

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)

如果我制作一个 $user->tokens->oldest('updated_at')->first()print_r 我得到这个:

[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] => *
        )

)

有人知道我的错误在哪里吗?

你能评论一下打印吗

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

我认为这是用户和 user_token 之间的混合体,因此不是要更新的明确实例。

您还可以查看 users_token table 结构(主键)。

Eloquent 不支持 复合 主键。

如果你想达到那个你应该覆盖两个方法并覆盖 $primary_key 属性。

App\UsersToken:

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',
    ];

    protected $primaryKey = [
        'user_id',
        'token',
    ];

    /**
     * Set the keys for a save update query.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    protected function setKeysForSaveQuery(\Illuminate\Database\Eloquent\Builder $query)
    {
        $keys = $this->getKeyName();
        if (! is_array($keys)) {
            return parent::setKeysForSaveQuery($query);
        }

        foreach ($keys as $keyName) {
            $query->where($keyName, '=', $this->getKeyForSaveQuery($keyName));
        }

        return $query;
    }

    /**
     * Get the primary key value for a save query.
     *
     * @param  mixed  $keyName
     * @return mixed
     */
    protected function getKeyForSaveQuery($keyName = null)
    {
        if (null === $keyName) {
            $keyName = $this->getKeyName();
        }

        return $this->original[$keyName] ?? $this->getAttribute($keyName);
    }
}

我尝试了很多不同的方法来在我的工作区中生成错误。我唯一能生成它的是 users_token table 中没有 id 列。 users_token table.

中似乎没有 id

如果未明确定义,Eloquent 将查找字段 id 作为任何 table 的主键。您可以使用 protected $primaryKey = 'token'; 在模型上定义主键字段名称。我假设您希望字段 token 作为主键。

但我建议不要使用 token 作为主要。使用普通的旧自增长整数作为主键,并使用 token 作为唯一键。这将防止任何不需要的重复条目。

其余代码看起来没问题。