ওপি যেমন তার মন্তব্যের অভ্যন্তরে বলেছিল: ডাটাবেস ডিজাইনটি ইতিমধ্যে সেট করা আছে এবং তাই লারাভেলের পলিমারফিক সম্পর্ক এখানে কোনও বিকল্প বলে মনে হচ্ছে না।
আমি ক্রিস নীলের উত্তরটি পছন্দ করি কারণ সম্প্রতি আমাকে অনুরূপ কিছু করতে হয়েছিল (ডিবেস / ডিবিএফ ফাইলগুলির জন্য এলওলিউর সমর্থন করার জন্য আমার নিজের ডেটাবেস ড্রাইভারকে লেখার জন্য) এবং লারাভেলের এলওভারেন্ট ওআরএম এর অভ্যন্তরীণ সাথে অনেক অভিজ্ঞতা অর্জন করেছিল।
আমি মডেল প্রতি সুস্পষ্ট ম্যাপিংয়ের সময় কোডটিকে আরও গতিশীল করার জন্য এটিতে আমার ব্যক্তিগত গন্ধ যুক্ত করেছি।
সমর্থিত বৈশিষ্ট্য যা আমি দ্রুত পরীক্ষা করেছি:
Animal::find(1)
আপনার প্রশ্নে জিজ্ঞাসা মত কাজ করে
Animal::all()
পাশাপাশি কাজ করে
Animal::where(['type' => 'dog'])->get()
AnimalDog
সংগ্রহ হিসাবে-অবজেক্টস ফিরে আসবে
- গতিশীল-শ্রেণীর জন্য গতিশীল অবজেক্ট ম্যাপিং যা এই বৈশিষ্ট্যটি ব্যবহার করে
Animal
কোনও ম্যাপিং কনফিগার করা না থাকলে (অথবা ডিবিতে একটি নতুন ম্যাপিং উপস্থিত হয়েছে) ক্ষেত্রে ফ্যালব্যাক থেকে মডেল
অসুবিধা:
- এটি মডেলের অভ্যন্তরীণ
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);
}
}