जैसा कि ओपी ने अपनी टिप्पणियों के अंदर कहा है: डेटाबेस का डिज़ाइन पहले से ही सेट है और इसलिए लारवेल के पॉलीमॉर्फिक संबंध यहां विकल्प नहीं हैं।
मुझे क्रिस नील का जवाब पसंद है क्योंकि मुझे हाल ही में ऐसा ही कुछ करना था (अपने डेटाबेस ड्राइवर को लिखने के लिए डबसे / डीबीएफ फ़ाइलों के लिए एलोकेंट का समर्थन करने के लिए) और लारवेल के एलोक्वेंट ओआरएम के आंतरिक लोगों के साथ बहुत अनुभव प्राप्त किया।
मैंने प्रति मॉडल एक स्पष्ट मानचित्रण रखते हुए कोड को अधिक गतिशील बनाने के लिए इसमें अपना व्यक्तिगत स्वाद जोड़ा है।
समर्थित सुविधाएँ जिन्हें मैंने जल्दी परीक्षण किया:
Animal::find(1)
आपके प्रश्न में पूछे गए अनुसार काम करता है
Animal::all()
साथ ही काम करता है
Animal::where(['type' => 'dog'])->get()
AnimalDog
एक संग्रह के रूप में वापसी करेंगे
- डायनामिक ऑब्जेक्ट मैपिंग प्रति एलोकेंट-क्लास जो इस विशेषता का उपयोग करता है
Animal
यदि कोई मैपिंग कॉन्फ़िगर नहीं की गई है (या डीबी में एक नई मैपिंग दिखाई गई है) तो -model पर वापस जाएँ
नुकसान:
- यह मॉडल के आंतरिक
newInstance()
और newFromBuilder()
पूरी तरह से (कॉपी और पेस्ट) फिर से लिख रहा है । इसका मतलब यह है कि अगर इस सदस्य कार्यों के लिए फ्रेमवर्क से कोई अपडेट होगा तो आपको कोड को हाथ से अपनाना होगा।
मुझे आशा है कि यह मदद करता है और मैं आपके परिदृश्य में किसी भी सुझाव, प्रश्न और अतिरिक्त उपयोग के मामलों के लिए तैयार हूं। यहां इसके उपयोग-मामले और उदाहरण दिए गए हैं:
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 {}
और यह एक उदाहरण है कि इसका उपयोग कैसे किया जा सकता है और इसके लिए संबंधित परिणामों के नीचे:
$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);
जिसके परिणामस्वरूप निम्नलिखित हैं:
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
और यदि आप चाहते हैं कि आप MorphTrait
यहां का उपयोग करें तो निश्चित रूप से इसके लिए पूर्ण कोड है:
<?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);
}
}