Untuk memeriksa apakah model yang diberikan terkait dengan model lain, yang Anda inginkan jika saya benar, yang Anda butuhkan hanyalah metode kecil ini yang memanfaatkan Eloquent sebaik-baiknya :
(Implementasikan di BaseModel , Entity atau ruang lingkup, apa pun yang cocok untuk Anda)
// usage
$task->isRelatedTo('transactions.users', $id);
// or
$template->isRelatedTo('tasks.transactions.users', Auth::user());
// or any kind of relation:
// imagine this: User m-m Transaction 1-m Item m-1 Group
$group->isRelatedTo('items.transaction.users', $id);
Keajaiban terjadi di sini:
/**
* Check if it is related to any given model through dot nested relations
*
* @param string $relations
* @param int|\Illuminate\Database\Eloquent\Model $id
* @return boolean
*/
public function isRelatedTo($relations, $id)
{
$relations = explode('.', $relations);
if ($id instanceof Model)
{
$related = $id;
$id = $related->getKey();
}
else
{
$related = $this->getNestedRelated($relations);
}
// recursive closure
$callback = function ($q) use (&$callback, &$relations, $related, $id)
{
if (count($relations))
{
$q->whereHas(array_shift($relations), $callback);
}
else
{
$q->where($related->getQualifiedKeyName(), $id);
}
};
return (bool) $this->whereHas(array_shift($relations), $callback)->find($this->getKey());
}
protected function getNestedRelated(array $relations)
{
$models = [];
foreach ($relations as $key => $relation)
{
$parent = ($key) ? $models[$key-1] : $this;
$models[] = $parent->{$relation}()->getRelated();
}
return end($models);
}
Hei, tapi apa yang terjadi di sana?
isRelatedTo() bekerja seperti ini:
-
periksa apakah lulus
$idadalah model atau hanya id, dan menyiapkan$relatedmodel dan$iduntuk digunakan dalam panggilan balik. Jika Anda tidak melewatkan objek maka Eloquent perlu membuat instance semua model terkait pada$relations(relation1.relation2.relation3...) rantai untuk mendapatkan yang kita minati - itulah yang terjadi digetNestedRelated(), cukup mudah. -
maka kita perlu melakukan sesuatu seperti ini:
// assuming relations 'relation1.relation2.relation3' $this->whereHas('relation1', function ($q) use ($id) { $q->whereHas('relation2', function ($q) use ($id) { $q->whereHas('relation3', function ($q) use ($id) { $q->where('id', $id); }); }); })->find($this->getKey()); // returns new instance of current model or null, thus cast to (bool) -
karena kita tidak tahu seberapa dalam relasi itu bersarang, kita perlu menggunakan recurrency. Namun kami meneruskan Penutupan ke
whereHas, jadi kita perlu menggunakan sedikit trik untuk memanggil dirinya sendiri di dalam tubuhnya (sebenarnya kita tidak menyebutnya, melainkan meneruskannya sebagai$callbackkewhereHasmetode, karena yang terakhir mengharapkan Penutupan sebagai param ke-2) - ini mungkin berguna bagi mereka yang tidak terbiasa Fungsi PHP rekursif anonim :// save it to the variable and pass it by reference $callback = function () use (&$callback) { if (...) // call the $callback again else // finish; } -
kami juga meneruskan ke penutupan
$relations(sebagai array sekarang) dengan referensi untuk melepaskan elemen-elemennya, dan ketika kami mendapatkan semuanya (artinya kami menyarangkanwhereHas), akhirnya kita letakkanwhereklausa alih-alihwhereHasanother yang lain , untuk mencari$related. kami model. -
akhirnya mari kita kembalikan
bool