2017-02-21 10 views
0

У меня есть следующие три таблицы:Laravel Eloquent получить данные из двух таблиц через промежуточную таблицу

users 
    id - integer 
    name - string 

tracker_sessions 
    id - integer 
    user_id - integer 
    geoip_id - integer 

tracker_geoip 
    id - integer 
    country - string 

Это мои модели:

class User extends Authenticatable 
{ 
    public function tracker_geoip(){ 
     return $this->hasManyThrough('App\TrackerGeo', 'App\TrackerSession', 'geoip_id', 'id', 'id'); 
    } 
    public function tracker_sessions(){ 
     return $this->hasMany('App\TrackerSession'); 
    } 
} 

class TrackerGeo extends Model 
{ 
    protected $table = 'tracker_geoip'; 
} 

class TrackerSession extends Model 
{ 
    protected $table = 'tracker_sessions'; 
} 

Можно ли получить этот результат с помощью красноречивых? :

0 => [ 
    'name' => 'John Smith', 
    'geoip' => ['id' => 12, 'country' => 'Greenland'] 
] 

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

$usersWithGeo = App\User::with('tracker_geoip')->get()->toArray(); 

Это делает возвращает массив информации о пользователе, но массив tracker_geoip к югу всегда пусто, даже если есть записи в таблицах.

+0

Зачем вам нужна модель для * tracker_sessions *? Laravel будет обрабатывать отношения «многие ко многим» автоматически для вас. – TheFallen

+0

@ TheFallen на самом деле он не использует сводную таблицу. так что ему нужна модель – xhulio

+0

, вы пробовали использовать метод 'load()'. i.e 'App \ User :: load ('tracker_geoip');' –

ответ

0

Глядя на вашу структуру таблицы, отношение для tracker_geoip должно фактически быть belongsToMany не hasManyThrough.

return $this->belongsToMany('App\TrackerGeo', 'tracker_sessions', 'user_id', 'geoip_id')->distinct(); 

Надеюсь, это поможет!

+0

Спасибо! Ваше предложение действительно сработало, но теперь в массиве «tracker_geoip» есть много дублированных индексов. Он имеет такое же количество индексов, сколько и количество сеансов пользователя. Любая вероятность, что я могу получить только один индекс, например: «tracker_geoip» => ['id' => 12, 'country' => 'Greenland']. Может быть, фильтр с подзапросом? – user3102290

+0

В этом случае вам просто нужно добавить 'distinct()' к вашим отношениям. Я обновил свой ответ, чтобы показать это. –

+0

Хорошо, что отлично работает, большое спасибо. – user3102290

0

попробуйте следующий код (избегая отношения):

class TrackerSession extends Model 
{ 
    public function getGeoipNameAttribute(){ 
     return TrackerGeo::where('id', $this->attributes['geoip_id'])->first(); //you can stop here or add ->country; to get only the country name 
    }; 
} 

выше метод извлекает имя Страны TrackerGeo коллекции с заданным идентификатором.

Теперь вам нужны все сеансы трекера для данного пользователя. Таким образом, в модели пользователя мы имеем:

public function getTrackerSessionAttribute(){ 
    return TrackerSession::where('user_id', %this->attributes['id'])->get() //or first() depends on the number of records you want to retrieve. 
} 

и на ваш взгляд, вы можете сделать следующее:

$user->tracker_session->geoip_name // ->country depends on the return result 

если вы извлекаться только 1 запись с красноречивым способом first() или

@foreach($user->tracker_session as $session) 
    {{$session->geoip_name}} // {{$session->geoip_name->country}} depends on the return result 
@endforeach 

Обратите внимание, что вы можете получить доступ к коллекциям, используя имя змеиного метода, как атрибут основной модели.

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