Дистанционный HasManyThrough

У меня есть четыре модели:

  1. пользователь
  2. клиент
  3. хранить
  4. Возможность

Отношения определяются так:

  • Пользователь hasMany Client
  • Клиент имеет много магазина
  • Магазин имеет много возможностей
  • Пользователь имеет много через магазин, клиент (это работает)

Проблема в том, что я пытаюсь получить доступ к отношениям User-> Opportunity через встроенные отношения Laravel, но не похоже, что я могу сделать это без пользовательского запроса или дополнительного столбца user_id в таблице возможностей, чтобы позволить прямой доступ (даже если можно сделать вывод из отношений Store-> Client). Я тоже не фанат вложенных foreach петли, если их можно избежать.

Мой вопрос:

Есть ли способ пойти на один уровень глубже и получить прямой доступ к возможностям пользователя в этом сценарии? Фактический код модели и все соответствующие отношения следующие:

пользователь

class User extends Eloquent{
public function clients(){
return $this->hasMany('Client');
}
public function stores(){
return $this->hasManyThrough('Store', 'Client');
}
public function proposals(){
return $this->hasMany('Proposal');
}
public function opportunities(){ //This does the job, but I feel like it could be better
return Opportunity::join('stores', 'stores.id', '=', 'opportunities.store_id')->
join('clients', 'clients.id', '=', 'stores.client_id')->
join('users', 'users.id', '=', 'clients.user_id')->
select('opportunities.*')->
where('users.id', $this->id);
}
public function getOpportunitiesAttribute(){ //This just helps mimic the hasManyThrough shorthand
return $this->opportunities()->get();
}
}

клиент

class Client extends Eloquent{
public function stores(){
return $this->hasMany('Store');
}
public function user(){
return $this->belongsTo('User');
}
public function opportunities(){
return $this->hasManyThrough('Opportunity', 'Store');
}
}

хранить

class Store extends Eloquent {
public function client(){
return $this->belongsTo('Client');
}
public function opportunities(){
return $this->hasMany('Opportunity');
}
}

Возможность

class Opportunity extends Eloquent {
public function store(){
return $this->belongsTo('Store');
}
}

2

Решение

Я не думаю, что есть такой метод в Laravel. Вы должны создать свой собственный запрос. Этот пользовательский запрос может быть очень дорогим, так как будет выполнено несколько запросов. Таким образом, оптимальное решение для этого, по моему мнению, состоит в том, чтобы связать пользователя и возможность с внешним ключом.

Однако, если вы не хотите связывать пользователя и возможность с внешним ключом, вы можете создать собственный запрос для обработки этого. Просто добавьте отношение «hasManyThrough» между Opportunity и моделью клиента, например,

    <?php
class Client extends Eloquent{
public function store(){
return $this->hasMany('Store');
}
public function user(){
return $this->belongsTo('User');
}

public function opportunity(){
return $this->hasManyThrough('Opportunity', 'Store');
}
}

Затем создайте статическую функцию в пользовательской модели.

    <?php

class User extends Eloquent implements UserInterface, RemindableInterface {

use UserTrait, RemindableTrait;

public function client(){
return $this->hasMany('Client');
}
public function store(){
return $this->hasManyThrough('Store', 'Client');
}

public static function getOpportunityOfUser($userId)
{
$clients = User::find($userId)->client;

foreach ($clients as $client) {
$opportunities[] = Client::find($client->id)->opportunity;
}

return $opportunities;
}
}

Теперь вы можете получить доступ к Возможности, предоставленной Пользователю за один раз,

    Route::get('/', function()
{
return $usersOpportunities = User::getOpportunityOfUser(1);
});

Это вернет все возможности всех клиентов, связанных с Пользователем с идентификатором «1».

0

Другие решения

Я создал HasManyThrough отношения с неограниченными уровнями: Репозиторий на GitHub

После установки вы можете использовать его так:

class User extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

public function opportunities() {
return $this->hasManyDeep(Opportunity::class, [Client::class, Store::class]);
}
}
0

По вопросам рекламы [email protected]