Laravel属于ToMany功能

时间:2014-09-15 11:33:54

标签: php laravel

我使用Laravel创建具有以下功能的基本网站:用户可以关注某些主题。我有一个'用户'表,a'主题'桌子,作为一个支点表,我有一个'跟随'表

users
----
user_id (primary)
user_first_name
etc..


following
---------
follow_id
user_id (foreign)
topic_id (foreign)


topics
------
topic_id (primary)
topic_name
etc...

我尝试创建一个显示所有主题的页面,但是对于当前用户关注的主题,我需要在框中显示重叠。

我有一个具有以下功能的用户模型:

public function follows() {
    return $this->belongsToMany('Topic', 'following', 'user_id', 'user_id');
}

但是,我不太确定从哪里开始(或者这是否正确!)

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

首先,你在follow方法上犯了一个错误。 您在本地和外国ID' user_id'。

上具有相同的变量名称

然后, 您是否已经向用户添加了主题? 如果是,那么如果您在主题模型

上的用户模型中执行相同操作将会很棒
public function followedBy()
{
    return $this->belongsToMany('User', 'following', 'topic_id', 'user_'id');
}

从这里开始,您可以通过

向用户添加以下主题
$user->following()->attach($topic_id);

$user->following()->attach([$first_topic, $second, $third, ...]);

您也可以使用同步方法,但这将删除用户与不在数组中的主题之间的所有先前关系。

要检索所有信息,您只需执行以下操作:

foreach ($user->following as $topic) {};

/!\不要在括号中添加括号,否则您将获得QueryBuilder而不是主题集合。 /!\

如果您想添加更多过滤器(例如仅限活动主题)

foreach ($user->following()->active()->get() as $topic) {}

请注意,我在这里添加了必需的括号,因为我不直接想要主题,而是使用QueryBuilder来过滤结果。 完成过滤后调用 - > get()方法。

(假设你的模型中有一个名为scopeActive()的方法) 请参阅Laravel范围:http://laravel.com/docs/eloquent#query-scopes

您可以通过以下方式在主题方面做相反的事情:

foreach ($topic->followedBy as $user) {}
PS:对不起我的英语,如果你误解了什么。不是我的母语。

答案 1 :(得分:2)

您在用户模型中维持以下功能

public function follows() {
   return $this->belongsToMany('Topic', 'following');
}

并使用以下语句检索任何用户的所有主题

$topics = User::find(1)->follows;

其中1是特定用户的用户ID。

答案 2 :(得分:1)

几乎在那里,follows()关系需要像这样:

public function follows() {
    return $this->belongsToMany('Topic', 'following', 'user_id', 'topic_id');
}

然后,你应该能够通过这样做来获取与当前用户相关的主题:

$topicsUserIsFollowing = Auth::user()->follows;

要开始关注主题,您可以执行此操作(假设您拥有主题的ID):

Auth::user()->follows()->attach($topic_id);

修改 如果您想查看某人是否跟随某个主题,那么在您的Topic模型中添加如下函数:

public function isFollowedBy($user)
{
    return $user->follows->contains($this->topic_id);
}

那么你可以这样做:

$currentUser = Auth::user();

$topics = Topics::all();

foreach($topics as $topic) {
   echo $topic->topic_name;
   if( $topic->isFollowedBy($currentUser) ){
       echo ' - [Already following this topic]';
   }  else {
       echo ' - [Follow this topic]';
   }  
}

你想把循环放在你的视图中,这只是为了说明

答案 3 :(得分:1)

1 在您的设置中,您使用非默认主键(topic_id / user_id / follow_id代替id),所以请务必使用设置:

protected $primaryKey = 'topic_id';

相应地在每个模型上。

2 我建议重新命名关系 - follows是不明确的,除非你在那里有3个模型。

3 您对当前设置的关系,如@ChainList已建议的那样:

public function follows()
{
  return $this->belongsToMany('Topic', 'following', 'user_id', 'topic_id');
}

4 为了检查用户是否已经按照指定主题进行操作,请执行以下操作:

// I Assume logged in user
$user = Auth::user();
$topics = Topic::all();

// somewhere in your view
@foreach ($topics as $topic)
  {{ $topic->name }} 
  @if ($user->follows->contains($topic->id))
    Already following this topic
  @else
    Follow this topic (put a link here or whatever)
  @endif
@endforeach

这样,当您第一次致电$user->follows时,您只会针对用户的主题运行一次查询。


我的建议是:

// leave id as primary key, it will make your life easier

// rename relation to
public function topics()
{
  // rename table name to something meaningful
  return $this->belongsToMany('Topic', 'topic_user'); // laravel convention

  // or if you like topics_followers
}