Laravel: обновить самый старый токен пользователя - PullRequest
0 голосов
/ 06 апреля 2020

В настоящее время я работаю над созданием API с использованием Lumen. У меня, например, 2 таблицы users и users_token с соответствующими моделями User и UsersToken:

Приложение \ Пользователь:

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

В таблице users_token есть 2 поля для импорта: user_id (внешний ключ связан с полем id из таблицы users) и token (простая строка).

В моей модели User у меня есть метод tokens, который возвращает все токены от пользователя с помощью функции hasMany():

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

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

Таблица users_token также содержит поля по умолчанию created_at и updated_at. Поэтому, чтобы получить самый старый измененный токен пользователя, я решил использовать функции oldest() и first() Laravel:

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

Итак, мне просто нужно обновить значение token об этом и, наконец, save() it:

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

Но, к сожалению, я получаю это сообщение об ошибке:

SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец 'id' в выражении «где» (SQL: обновить users_token установить token = тест, users_token. updated_at = 2020-04-06 17:34:59 где id равно нулю)

Если я получу print_r из $user->tokens->oldest('updated_at')->first(), я получу это:

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

)

У кого-нибудь есть идея, где моя ошибка?

Ответы [ 3 ]

2 голосов
/ 08 апреля 2020

Не могли бы вы рассмотреть печать

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

Я думаю, что это гибрид между пользователем и user_token, поэтому не является четким экземпляром для обновления.

Также вы можете просмотреть структуру таблицы users_token ( первичный ключ).

1 голос
/ 08 апреля 2020

Я пробовал много разных способов вызвать ошибку в моей рабочей области. Единственный раз, когда я мог его сгенерировать, это отсутствие столбца id в таблице users_token И похоже, что в таблице users_token нет столбца id.

Если явно не определено, Eloquent будет искать поле id в качестве первичного ключа для любой таблицы. Вы можете определить имя поля первичного ключа в модели, используя protected $primaryKey = 'token';. Я предполагаю, что вы хотите поле token в качестве первичного ключа.

Но я бы порекомендовал не использовать token в качестве основного. Используйте простое старое длинное целое число с автоинкрементом в качестве первичного ключа и используйте token в качестве уникального ключа. Это предотвратит любые нежелательные повторяющиеся записи.

Остальная часть кода выглядит хорошо.

1 голос
/ 08 апреля 2020

Eloquent не поддерживает составные первичные ключи.

, если вы хотите достичь этого, вы должны переопределить два метода и переопределить атрибут $primary_key.

in Приложение \ 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);
    }
}
...