首页 > 解决方案 > Laravel Eloquent - 模型扩展了其他模型

问题描述

我有一个关于扩展我自己的模型雄辩的问题。

在我目前正在处理的项目中,名为表modules,它包含项目模块列表、该模块的元素数量、添加日期等。

例如: id = 1; name = 'users'; count = 120; date_add = '2007-05-05';

并且这个实体调用users对应于模型User(表 - users),以便“计算”它的用户数

并更新count我们使用每天运行的脚本(我知道这不是好方法但是......你知道)。

在该脚本中是循环,并且在该循环内部有很多 if 语句(每个模块 1 个),并且在 if 内部有一个带有计数的单个查询。根据示例,它类似于:

foreach($modules as $module) {
    if($module['name'] == 'users') {
        $count = old_and_bad_method_to_count('users', "state = 'on'");
    }
}

function old_and_bad_method_to_count($table, $sql_cond) {}

所以它看起来很糟糕。

我需要稍微重构一下该代码,因为它使用危险函数而不是 Query/Builder 或 Eloquent/Model 并且看起来很糟糕。

我想出了一个想法,我将使用 Models 并创建 InterfaceElementsCountable并且所有没有接口的模型都将使用Model::all()->count(),而那些有接口的将使用 interface 方法:

foreach ($modules as $module) {
    $className = $module->getModelName();

    if($className) {
        $modelInterfaces = class_implements($className);
        if(isset($modelInterfaces[ElementsCountable::class])) {
            /** @var ElementsCountable $className */
            $count = $className::countModuleElements();
        } else {
            /** @var Model $className */
            $count = $className::all()->count();
        }
    }
}

在方法中,getModelName()我使用了我创建的 const 映射数组(表 -> 模型),因为很多模型都有自定义表名。

但是后来我意识到这将是一个好方法,但是其中有一些记录Modules使用同一个表,例如users_off使用与 相同的表users,但使用其他条件 -state = 'off'

所以事情有点复杂,有一个正确的问题:有一个很好的方法可以User在启动时扩展和添加范围吗?

class UserOff extends User
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope(function (Builder $builder) {
            $builder->where('state', '=', 'off');
        });
    }
}

因为我担心这是否是一个好的解决方案。因为该类的所有方法都需要该范围以及如何防止方法withoutGlobalScope()以及其他并发症呢?

标签: phplaravel

解决方案


我认为UserOff为此目的创建具有额外全局范围的模型是一个很好的解决方案。

我还认为我想要实施的解决方案可以让我做类似的事情


$count = $modules->sum(function ($module) {
    $className = $module->getModelName();

    return $className::modulesCount();
}

我将创建一个接口,该接口在每个模型上都需要ModulesCountable一个方法。modulesCount()modulesCount()方法将返回默认计数或您在countModuleElements().

如果有很多模型,我可能会使用特征DefaultModulesCount作为默认计数,也可能使用自定义版本,例如。ElementsModuleCount如果这是一致的。


推荐阅读