php - 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()
以及其他并发症呢?
解决方案
我认为UserOff
为此目的创建具有额外全局范围的模型是一个很好的解决方案。
我还认为我想要实施的解决方案可以让我做类似的事情
$count = $modules->sum(function ($module) {
$className = $module->getModelName();
return $className::modulesCount();
}
我将创建一个接口,该接口在每个模型上都需要ModulesCountable
一个方法。modulesCount()
该modulesCount()
方法将返回默认计数或您在countModuleElements()
.
如果有很多模型,我可能会使用特征DefaultModulesCount
作为默认计数,也可能使用自定义版本,例如。ElementsModuleCount
如果这是一致的。
推荐阅读
- angular - 多次发出 RxJS http 请求
- apache-kafka - Kafka主题名称可以参数化吗?
- c++ - c ++简单删除向量重复导致分段错误
- authentication - 创建并激活没有权限的目录帐户
- android - Firebase 测试实验室 Android Emulator 或物理设备更新 WebView 版本
- docker - 解析 docker 容器内的站点主机名
- javascript - 自动向左水平滚动表格(使用 HTML、CSS 或 JQuery)
- lua - lua 子字符串替换 2 模式
- c++11 - Boost asio 解析器被单元化
- flutter - 如何将 DiagnosticableTreeMixin 与列表一起使用?