У меня есть четыре модели:
Отношения определяются так:
Проблема в том, что я пытаюсь получить доступ к отношениям 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');
}
}
Я не думаю, что есть такой метод в 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».
Я создал HasManyThrough
отношения с неограниченными уровнями: Репозиторий на GitHub
После установки вы можете использовать его так:
class User extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function opportunities() {
return $this->hasManyDeep(Opportunity::class, [Client::class, Store::class]);
}
}