OP'nin yorumlarında belirttiği gibi: Veritabanı tasarımı zaten ayarlanmış ve bu nedenle Laravel'in Polimorfik İlişkileri burada bir seçenek gibi görünmemektedir.
ben Chris Neal cevap gibi Geçenlerde benzer bir şey yapmak zorunda çünkü (dbase / DBF dosyaları için anlamlı desteklemek için kendi Veritabanı Sürücü yazma) ve laravel en Eloquent ORM dahili özelliklerine sahip bir çok deneyim kazanmıştır.
Model başına açık bir eşleme tutarken kodu daha dinamik hale getirmek için kişisel lezzetimi ekledim.
Hızla test ettiğim desteklenen özellikler:
Animal::find(1)
sorunuzda sorulduğu gibi çalışıyor
Animal::all()
de çalışıyor
Animal::where(['type' => 'dog'])->get()
geri dönücek AnimalDog
-objects bir koleksiyon olarak
- Bu özelliği kullanan her eloquent sınıfı için dinamik nesne eşleme
Animal
Hiçbir eşleme yapılandırılmadığında (veya DB'de yeni bir eşleme göründüğünde) -modele dönüş
Dezavantajları:
- Modelin dahili
newInstance()
ve newFromBuilder()
tamamen yeniden yazılması (kopyala yapıştır). Bu, çerçeveden bu üye işlevlerine herhangi bir güncelleme yapılacaksa, kodu elle benimsemeniz gerektiği anlamına gelir.
Umarım yardımcı olur ve senaryonuzda herhangi bir öneri, soru ve ek kullanım durumu için hazırım. Bunun kullanım örnekleri ve örnekleri:
class Animal extends Model
{
use MorphTrait; // You'll find the trait in the very end of this answer
protected $morphKey = 'type'; // This is your column inside the database
protected $morphMap = [ // This is the value-to-class mapping
'dog' => AnimalDog::class,
'cat' => AnimalCat::class,
];
}
class AnimalCat extends Animal {}
class AnimalDog extends Animal {}
Ve bu nasıl kullanılabileceğine ve bunun için ilgili sonuçların altında bir örnektir:
$cat = Animal::find(1);
$dog = Animal::find(2);
$new = Animal::find(3);
$all = Animal::all();
echo sprintf('ID: %s - Type: %s - Class: %s - Data: %s', $cat->id, $cat->type, get_class($cat), $cat, json_encode($cat->toArray())) . PHP_EOL;
echo sprintf('ID: %s - Type: %s - Class: %s - Data: %s', $dog->id, $dog->type, get_class($dog), $dog, json_encode($dog->toArray())) . PHP_EOL;
echo sprintf('ID: %s - Type: %s - Class: %s - Data: %s', $new->id, $new->type, get_class($new), $new, json_encode($new->toArray())) . PHP_EOL;
dd($all);
hangi sonuç aşağıdaki:
ID: 1 - Type: cat - Class: App\AnimalCat - Data: {"id":1,"type":"cat"}
ID: 2 - Type: dog - Class: App\AnimalDog - Data: {"id":2,"type":"dog"}
ID: 3 - Type: new-animal - Class: App\Animal - Data: {"id":3,"type":"new-animal"}
// Illuminate\Database\Eloquent\Collection {#1418
// #items: array:2 [
// 0 => App\AnimalCat {#1419
// 1 => App\AnimalDog {#1422
// 2 => App\Animal {#1425
Ve eğer kullanmak istiyorsanız MorphTrait
, elbette bunun için tam kod:
<?php namespace App;
trait MorphTrait
{
public function newInstance($attributes = [], $exists = false)
{
// This method just provides a convenient way for us to generate fresh model
// instances of this current model. It is particularly useful during the
// hydration of new objects via the Eloquent query builder instances.
if (isset($attributes['force_class_morph'])) {
$class = $attributes['force_class_morph'];
$model = new $class((array)$attributes);
} else {
$model = new static((array)$attributes);
}
$model->exists = $exists;
$model->setConnection(
$this->getConnectionName()
);
$model->setTable($this->getTable());
return $model;
}
/**
* Create a new model instance that is existing.
*
* @param array $attributes
* @param string|null $connection
* @return static
*/
public function newFromBuilder($attributes = [], $connection = null)
{
$newInstance = [];
if ($this->isValidMorphConfiguration($attributes)) {
$newInstance = [
'force_class_morph' => $this->morphMap[$attributes->{$this->morphKey}],
];
}
$model = $this->newInstance($newInstance, true);
$model->setRawAttributes((array)$attributes, true);
$model->setConnection($connection ?: $this->getConnectionName());
$model->fireModelEvent('retrieved', false);
return $model;
}
private function isValidMorphConfiguration($attributes): bool
{
if (!isset($this->morphKey) || empty($this->morphMap)) {
return false;
}
if (!array_key_exists($this->morphKey, (array)$attributes)) {
return false;
}
return array_key_exists($attributes->{$this->morphKey}, $this->morphMap);
}
}