Пользователь Laravel имеет много пользовательских классов

Меня интересует следующий вариант использования и самый простой и элегантный способ добиться этого в Laravel.

В основном у меня будет таблица пользователей

id, name, email, password

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

id user_id, suggested_id, reason

В моем классе пользователей достаточно просто связать эти два

    public function suggestedUsers()
    {
        return $this->hasMany(SuggestedUser::class);
    }

Так что теперь я могу сделать

$user->suggestedUsers и получить результаты сводной таблицы

=> Illuminate\Database\Eloquent\Collection {#1881
     all: [
       App\Models\PartnerSuggestion {#1939
         id: 1,
         user_id: 1,
         partner_id: 86,
         reason: "You liked similar posts",
         created_at: null,
         updated_at: null,
       },
     ],
   }

Но на самом деле я хочу вернуть коллекцию User::class вместо коллекции сводки.

так что, когда я выполняю $user->suggestedUsers, я получаю что-то вроде этого, включая причину

Illuminate\Database\Eloquent\Collection {#1940
     all: [
       App\Models\User {#1941
         id: 86,
         first_name: "Eugene",
         last_name: "Simonis",
         reason: "You liked similar posts"
       },
       App\Models\User {#1942
         id: 95,
         first_name: "Wilfred",
         last_name: "Stamm",
         reason: "They viewed your profile"

       },
     ],
   }

Мой вопрос действительно заключается в том, каким будет самый чистый и элегантный способ сделать это? Нужно ли мне избавиться от сводной таблицы и создать связь, которая ссылается сама на себя? Я просмотрел такие пакеты, как baum, но по причинам (последний активный 4 года назад) я бы предпочел сделать это без пакета.


person Devin Gray    schedule 17.05.2020    source источник
comment
Я думаю, вы можете сделать что-то вроде этого: $user-›suggestedUsers-›pluck('user')   -  person Ali Lashini    schedule 17.05.2020


Ответы (2)


На мой взгляд, вы слишком все усложняете. Возможно, вам не нужна целая модель для решения вашей проблемы.

Чего вы на самом деле хотите достичь, так это отношения «многие ко многим» с моделью пользователя на обе стороны.

На этот вид отношений в Laravel ссылается следующая внутренняя модель пользователя:

public function usersIsSuggestedTo() {
    return $this->belongsToMany(User::class, 'suggested_user', 'suggested_id', 'user_id');
}

public function suggestedUsers() {
    return $this->belongsToMany(User::class, 'suggested_user', 'user_id', 'suggested_id');
}

Вам также необходимо создать миграцию для таблицы suggested_user.

Затем вы получаете доступ к коллекции предложенных пользователей с помощью $user->suggestedUsers и к сводной таблице (это таблица, объединяющая их) с помощью $user->suggestedUsers->pivot.

Получение reason в запрашиваемой коллекции

Вы также можете добавить поле reason к своим отношениям, используя ->withPivot('reason') в своих отношениях, как показано ниже:

return $this->belongsToMany(User::class, 'suggested_user', 'user_id', 'suggested_id')->withPivot('reason');

-

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

Эта ссылка на официальную документацию может быть вам полезна: https://laravel.com/docs/7.x/eloquent-relationships#many-to-many

person Karol Sobański    schedule 17.05.2020
comment
Этот способ работает и действительно удобен, мне нравится его простота, я думаю только о том, чтобы получить предлагаемую причину в запросе, похоже, мне понадобится оператор соединения для запуска на каждой модели. - person Devin Gray; 17.05.2020
comment
@DevinGray на самом деле reason является частью сводного ответа, и вы автоматически извлекаете его с помощью ->pivot. Просто следуйте документам, которые я связал;) - person Karol Sobański; 17.05.2020
comment
@DevinGray Я отредактировал ответ, чтобы вам было проще - person Karol Sobański; 17.05.2020
comment
Я собираюсь принять этот ответ, поскольку технически он решает вопрос, который я задал. Спасибо. На практике я выбрал морфируемые столбцы БД, так как с ними я могу быть немного более гибким. Но это решение отличное - person Devin Gray; 17.05.2020

Мне удалось решить проблему, используя полиморфное отношение и черту.

trait HasSuggestions
{
    public function suggestions()
    {
        return $this->morphMany(PartnerSuggestion::class, 'user');
    }

    public function suggest(Model $suggestedUser)
    {

        $suggestion = (new UserSuggestion())->fillSuggestion($suggestedUser)->fill([
            'reason' => 'reason',
        ]);
        $this->suggestions()->save($suggestion);
        return $suggestion;
    }
}

затем в моей БД вместо полей идентификатора я использую поля морфинга

$table->morphs('user');
$table->morphs('suggested_user');

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

eg:

$user->getSuggested
$user->getSuggestedByDate

так далее

person Devin Gray    schedule 17.05.2020