【问题标题】:Laravel User Has Many User classLaravel 用户有很多用户类
【发布时间】:2020-09-03 02:55:18
【问题描述】:

我想知道以下用例以及在 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 年前),我宁愿在没有软件包的情况下这样做

【问题讨论】:

  • 我认为你可以这样做:$user->suggestedUsers->pluck('user')

标签: php laravel eloquent laravel-7


【解决方案1】:

我设法通过使用多态关系和特征解决了这个问题。

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;
    }
}

然后在我的数据库中,我使用 morph 字段而不仅仅是 id 字段

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

通过使用这个特性,我仍然可以得到相同的结果,但我现在可以在其上添加一个新方法,该方法将使用查询构建器,这样我就可以创建很多查询

例如:

$user->getSuggested
$user->getSuggestedByDate

【讨论】:

    【解决方案2】:

    在我看来,你把事情复杂化了。可能你不需要一个完整的模型来解决你的问题。

    您真正想要实现的是与双方上的用户模型的多对多关系。

    Laravel 中的这种关系在 User 模型中引用如下:

    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

    您还可以使用->withPivot('reason')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

    【讨论】:

    • 这种方式有效而且非常方便,我确实喜欢这种简单性,我也只想在查询中获得建议的原因,似乎我需要一个连接语句才能运行在每个模型上
    • @DevinGray 实际上 reason 是数据透视响应的一部分,您可以使用 ->pivot 自动检索它。只需按照我链接的文档 ;)
    • @DevinGray 我已经编辑了答案以方便您使用
    • 我将接受这个答案,因为从技术上讲它解决了我提出的问题。谢谢你。在实践中,我选择了可​​变形的 DB 列,因为我可以更灵活地使用它。但是这个解决方案很棒
    猜你喜欢
    • 2019-02-19
    • 1970-01-01
    • 2018-07-26
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多