Laravel 8:获取特定关系的“morphOne”类的所有模型的类名

Posted

技术标签:

【中文标题】Laravel 8:获取特定关系的“morphOne”类的所有模型的类名【英文标题】:Laravel 8: Get the class names of all Models that "morphOne" class of a specific relation 【发布时间】:2021-09-10 13:40:54 【问题描述】:

我需要一个与另一个特定模型具有 OneToOne 或 OneToMany 多态关系定义的所有模型的类名列表。这个列表不能基于对应数据库表中实际存在的关系,而是基于代码定义。

示例

A、B 和 C 类与 X 类(*able 类)具有多态的一对一或一对多关系。

我正在搜索(现有的?)方法来检索 A、B 和 C(或与 X 具有相同关系的任何其他类)的类名。

【问题讨论】:

【参考方案1】:

MorphOne 关系的逆是MorphTo 关系。但是,在 Eloquent 中,这种关系并没有定义与自身具有 MorphOne 关系的所有模型。

解决方案 A

一个简单的解决方案是在 X 类上记录一个静态数组,该数组包含该关系的所有可能类,就像这样。

class X extends Model

    public static array RELATION_OPTIONS = [
        App\A::class,
        App\B::class,
        App\C::class,
    ];

    public function foo(): MorphTo
    
        return $this->morphTo();
    

此解决方案的缺点是您必须使模型选项数组与反向关系的实际实现保持同步。因此,每当您将具有MorphOne 关系的另一个模型添加到X 时,您都需要将其添加到RELATION_OPTIONS 数组中。

解决方案 B

另一种解决方案是使用循环所有Models 来确定它们中的哪些与X 有关系。在伪代码中,这意味着您将不得不这样做:

$models = get_all_models(); // \Illuminate\Support\Collection
$models->filter(function (Model $model) 
    if ( ! method_exists($model, 'foo')) return false;

    $relation = $model->foo();

    if ( ! $relation instanceof MorphOne) return false;

    return $relation->getParent() instanceof X;
);

这是一个不太简单但更准确的解决方案,始终与实际实施保持同步。但请注意,您需要缓存此方法的执行,因为查找应用程序中的所有模型(通过循环文件系统)可能是一项昂贵的任务。

【讨论】:

嗨,erikgaal,非常感谢您的解释。解决方案 A 就是我现在正在做的事情。解决方案 B 是我正在寻找的那种解决方案。是否有可能以某种方式使用 Laravel 缓存功能进行缓存?还是我必须自己实现一些东西。 如果您将此逻辑抽象为某个方法,您可以通过在模型上使用静态属性“缓存”它并确保只设置一次(在启动时或需要该属性时) )。这样,每个请求只运行一次。另一种方法是使用 Laravel 的 Cache 系统,但这会使它再次变得更加复杂。

以上是关于Laravel 8:获取特定关系的“morphOne”类的所有模型的类名的主要内容,如果未能解决你的问题,请参考以下文章

在 hasMany 关系 Laravel 上获取具有特定值的单个项目

在 Laravel Eloquent 中使用关系表中的特定列获取表中的特定列

在 Laravel Eloquent 中获取 HasOne 关系中的特定列

Laravel从模型中获取具有特定数据和关系的记录

试图从 laravel 8 上的数据库中获取特定记录

在 Laravel Eloquent 中获取和过滤关系