Laravel Eloquent 父级具有多个多态子级

问题描述 投票:0回答:1

我一直在尝试在 Laravel 中对

ShapeContainer
实体和具有独特属性的不同形状之间的关系进行建模,但有一个通用的
Shape
接口(具有
getArea
getPerimeter
方法)。我已经阅读了 laravel 文档中的示例(
posts
videos
comments
),但在该示例中,子实体 (
Comment
) 可以属于不同类型的父实体。就我而言,我希望父实体(
ShapeContainer
)能够处理不同类型的子实体(
Circle,
Rectangle
等)。

我想要的最终结果是这样的:

$shapeContainer = ShapeContainer::find(1);
$shapes = $shapeContainer->shapes()

foreach($shapes as $shape) {
    $area = $shape->getArea();
}

我现在设法实现这一目标的方法是在两者之间添加一个实体,比如枢轴

class Shape extends Model
{

    public function shapeable()
    {
        return $this->morphTo('shapeable');
    }

    public function shapeConatiner()
    {
        return $this->belongsTo(ShapeContainer::class);
    }
}

与相应的表字段

shape_container_id # Reference to the shape container
shapeable_type # square/circle
shapeble_id # Reference to the ID of the corresponding shape model.

所以在代码中我可以做到

$shapeContainer = ShapeContainer::find(1);
$shapes = $shapeContainer->shapes()

foreach($shapes as $shape) {
    $area = $shape->shapable->getArea();
}

我想知道这是正确的方法,因为我没有在 laravel 文档中识别出与我的用例类似的任何内容,并且在两者之间建立一个完整的模型来解释这种关系似乎很笨拙。是否有可能保留该数据透视表,但简化界面,以便使用模型的开发人员不必担心或看到

shapeable()
数据透视表?

laravel database eloquent database-design polymorphism
1个回答
0
投票

听起来您需要在创建模型时将模型转换为其即时类型,然后每个实例都可以有自己的版本

getArea

尝试在内部实现类似的东西

Shape

// Override the newFromBuilder method
public function newFromBuilder($attributes = [], $connection = null) {
        
   $class = $attributes-> shapeable_type ?? self::class;

   if (class_exists($class)) {
       $model = (new $class)->newInstance((array) $attributes, true);
   } else {
       // If the class doesn't exist, fallback to the parent
       $model = parent::newFromBuilder($attributes, $connection);
   }
   $model->setRawAttributes((array) $attributes);
   return $model;

}
© www.soinside.com 2019 - 2024. All rights reserved.