Я использую Laravel для создания базового сайта со следующей функцией: пользователь может следить за определенными темами. У меня есть таблица ‘users’, таблица ‘themes’, а в качестве сводной таблицы у меня есть таблица ‘follow’.
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');
}
Тем не менее, я не слишком уверен, куда идти отсюда (или это правильно!)
Был бы очень благодарен за любую помощь.
Прежде всего, вы допустили ошибку в своем следующем методе.
У вас одинаковое имя переменной с локальным и внешним идентификатором ‘user_id’.
Затем,
Вы уже добавили тему для пользователя?
Если да, было бы здорово, если бы вы сделали то же самое, что и в вашей модели User на модели Topic.
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: простите за мой английский, если вы что-то не так поняли. Не мой родной язык.
Вы поддерживаете следующую функцию в пользовательской модели
public function follows() {
return $this->belongsToMany('Topic', 'following');
}
и используйте оператор ниже, чтобы получить все темы любого пользователя
$topics = User::find(1)->follows;
Где 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
}
Почти там follows()
отношения должны быть такими:
public function follows() {
return $this->belongsToMany('Topic', 'following', 'user_id', 'topic_id');
}
Затем вы сможете получить темы, связанные с текущим пользователем, выполнив следующее:
$topicsUserIsFollowing = Auth::user()->follows;
Чтобы начать следовать теме, вы можете сделать это (при условии, что у вас есть идентификатор темы):
Auth::user()->follows()->attach($topic_id);
редактировать
Если вы хотите увидеть, следует ли кто-то за темой, то в вашей модели Темы поместите такую функцию:
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]';
}
}
Вы хотели бы поставить цикл в вашем представлении, это просто для иллюстрации