2015-08-01 2 views
2

A Venue имеет много Subscriptions.Имеет много до

A Subscription имеет много Subscribers (User).

Theres сводная таблица, содержащая отношения между user_id и subscription_id.

Pivot for subscription and user_id

Как я могу получить все Subscribers от Venue?

Я попытался с:

class Venue { 
    /** 
    * Members 
    */ 

     public function members() { 
      return $this->hasManyThrough('App\User', 'App\Subscription'); 
     } 
} 

Но он терпит неудачу с MySQL ошибка:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'users.subscription_id' in 'on clause' (SQL: select `users`.*, `sub 
    scriptions`.`venue_id` from `users` inner join `subscriptions` on `subscriptions`.`id` = `users`.`subscription_id` where ` 
    users`.`deleted_at` is null and `subscriptions`.`venue_id` = 1) 

Как моя Subscription модель взгляд:

`Subscription` 

class Subscription extends Model { 

    protected $table = 'subscriptions'; 

    /** 
    * Subscripers 
    */ 

     public function subscribers() { 
      return $this->belongsToMany('App\User'); 
     } 

    /** 
    * Venue 
    */ 

     public function venue() { 
      return $this->belongsTo('Venue'); 
     } 

} 
+0

Что именно является 'Subscription' в вашем приложении? Для меня это похоже на то, что вы хотите достичь того, что «Пользователь» может подписаться на «Место проведения», но это будет отношение n: m без дополнительной модели «Subscription» (не уверен, что вы могли бы использовать его дополнительно).Дополнительная информация может быть сохранена как элементы поворота. – Namoshek

+0

Я обновил свой ответ. У меня сводная таблица, содержащая связь между пользователем и подпиской. – FooBar

+0

Это потому, что ваша концепция неверна. Вам не нужна модель Subacription, потому что вы можете иметь прямое отображение n: m между пользователем и местом. Посмотрите документацию для многих-ко-многим. – Namoshek

ответ

0

Простой вопрос: Почему вы используете третья модель для 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() 
+0

Благодарим вас за ответ, но этого я не пытаюсь достичь. Я не хочу отношения place_user, потому что «Пользователь» принадлежит месту, ТОЛЬКО, если «Пользователь» имеет «Подписка» с «Местом». Мое отношение к базе данных: http://www.laravelsd.com/share/AAjuYS – FooBar

+0

Просьба предоставить более подробную информацию о том, что такое подписка, что она делает (или стоит) и какую другую информацию она содержит. – Namoshek

+0

Моя модель «Подписки»: http://laravel.io/bin/jQlvG – FooBar

Смежные вопросы