У меня есть полиморфное отношение, в котором класс (запрос) может иметь отношение либо к классу (отпуск), либо к классу (сверхурочная работа).
Каждый объект класса (Запрос) принадлежит пользователю.
Я хотел бы установить отношения в классе User, чтобы напрямую получать все их объекты Leave или Overtime.
Вот как выглядит код:
class Request extends Model
{
public function requestable() {
return $this->morphTo();
}
public function user() {
return $this->belongsTo('App\User');
}
}
class Leave extends Model
{
public function request() {
return $this->morphOne('App\Request', 'requestable');
}
}
class Overtime extends Model
{
public function request() {
return $this->morphOne('App\Request', 'requestable');
}
}
class User extends Authenticatable
{
public function requests() {
return $this->hasMany(Request::class);
}
public function leaves() {
// Need help here
}
public function overtimes() {
// And here
}
}
Что я хотел бы сделать, так это получить все отпуска и сверхурочные, которые есть у пользователя, поэтому в конечном итоге я должен сделать это:
$userLeaves = $user->leaves;
$userOvertimes = $user->overtimes;
Не могли бы вы попробовать? Я не думаю, что это работает с полиморфными отношениями.
Кажется, вам нужна комбинация полиморфного отношения (которое вы уже определили) и hasManyThrough.
return $this->hasManyThrough(Leave::class, Request::class);
а также
return $this->hasManyThrough(Overtime::class, Request::class);
соответственно. Но проверьте внешние и локальные ключи (см. подробнее здесь).
Да, я считаю, что hasManyThrough — это решение, но независимо от того, сколько комбинаций я пробовал с иностранными/локальными ключами, я не мог заставить его работать, может быть, попробовать?
Я никогда не пользовался такими отношениями. Возможно, вам нужно указать тип связанной полиморфной модели. Попробуйте использовать это.
вы можете получить пользовательские листья и сверхурочные через пользовательские запросы, используя
$requests = $user->requests->with('requestable');
но это будет извлекать все пользовательские запросы, не зависящие от типа, однако вы можете получить их в зависимости от типа, используя функцию листьев и сверхурочной работы, если хотите, и указав тип там
Класс пользователя
public function leaves()
{
return $this->requests->where('requestable_type', 'App\Leave');
}
public function overTimes()
{
return $this->requests->where('requestable_type', 'App\OverTime');
}
Но это вернет объекты типа Request, а не объекты отпуска или сверхурочной работы.
Отвечая на мой собственный вопрос.
Использование hasManyThrough
:
public function leaves() {
return $this->hasManyThrough(
Leave::class, // the class that we want objects from
Request::class, // the class sitting between this one and the target
'user_id', // this class's foreign key in the request class
'id', // foreign key in leave class
'id', // local key in this class
'requestable_id' // key of the leave in the request class
)
// we have to limit it to only Leave class
->where('requestable_type', array_search(Leave::class, Relation::morphMap()) ?: Leave::class);
}
public function overtimes() {
return $this->hasManyThrough(
Overtime::class, // the class that we want objects from
Request::class, // the class sitting between this one and the target
'user_id', // this class's foreign key in the request class
'id', // foreign key in overtime class
'id', // local key in this class
'requestable_id' // key of the overtime in the request class
)
// we have to limit it to only overtime class
->where('requestable_type', array_search(Overtime::class, Relation::morphMap()) ?: Overtime::class);
}
Пожалуйста, пометить ответ как принятый. Это показывает другим пользователям, что проблема решена.
Является ли отношение hasManyThrough тем, что вы ищете? laravel.com/docs/5.8/eloquent-relationships#имеет много сквозных. Или вы можете использовать ->hasMany()->where();