Простой вопрос: Почему вы используете третья модель для Subscriptions
? Это звучит как нормальное отношение n: m между User
и Venue
, как уже написано в комментариях выше.
class User {
public function venues() {
return $this->belongsToMany('App\Venue');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User');
}
}
Это созвездие фактически необходимо три таблицы, которые (я дал каждой модели столбец name
):
users
- id
- name
venues
- id
- name
user_venue
- user_id
- venue_id
Но чтобы получить доступ к отношениям, вы можете просто использовать Красноречивые магии:
// List of all venues (as Venue models) that are in relation with User with id $id
$venues = User::find($id)->venues()->get();
// Returns the alphabetically first user that has a relation with Venue with id $id
$user = Venue::find($id)->users()->orderBy('name', 'asc')->first();
Если вам нужно сохранить дополнительную информацию в сводной таблице (например, когда отношение установлено), вы можете использовать дополнительные поля поворота:
user_venue
- user_id
- venue_id
- created_at
class User {
public function venues() {
return $this->belongsToMany('App\Venue')->withPivot('created_at');
}
}
class Venue {
public function users() {
return $this->belongsToMany('App\User')->withPivot('created_at');
}
}
// Returns the date of the relations establishment for the alphabetically
// first Venue the User with id $id has a relation to
$created_at = User::find($id)->venues()->orderBy('name', 'asc')->first()->pivot->created_at;
Я никогда не пытался делать то, что вы пытаетесь сделать там, потому что кажется (с текущей информацией) концептуально неправильно. Я также не знаю, можно ли создать собственную модель для сводной таблицы, но я думаю, что она должна работать, если сводная таблица имеет собственный первичный столбец идентификатора. Вероятно, это может быть полезно, если у вас есть третья модель, которая должна быть связана с соединением двух других, но обычно этого не происходит. Поэтому сначала попробуйте его с помощью сводных таблиц, как показано выше.
Хорошо, я до сих пор не вижу в этом хорошего варианта использования, но я могу предоставить вам запрос, который работает. К сожалению, я не смог получить запрос Eloquent, но решение все равно было бы неплохо.
class Venue {
public function members($distinct = true) {
$query = User::select('users.*')
->join('subscription_user', 'subscription_user.user_id', '=', 'users.id')
->join('subscriptions', 'subscriptions.id', '=', 'subscription_user.subscription_id')
->where('subscriptions.venue_id', '=', $this->id);
if($distinct === true) {
$query->distinct();
}
return $query;
}
}
Отношение может быть запрошен только в обычном режиме:
Venue::find($id)->members()->get()
// or with duplicate members
Venue::find($id)->members(false)->get()
Что именно является 'Subscription' в вашем приложении? Для меня это похоже на то, что вы хотите достичь того, что «Пользователь» может подписаться на «Место проведения», но это будет отношение n: m без дополнительной модели «Subscription» (не уверен, что вы могли бы использовать его дополнительно).Дополнительная информация может быть сохранена как элементы поворота. – Namoshek
Я обновил свой ответ. У меня сводная таблица, содержащая связь между пользователем и подпиской. – FooBar
Это потому, что ваша концепция неверна. Вам не нужна модель Subacription, потому что вы можете иметь прямое отображение n: m между пользователем и местом. Посмотрите документацию для многих-ко-многим. – Namoshek