【发布时间】:2019-11-17 15:37:57
【问题描述】:
我正在使用 Laravel 框架。我尽可能使用模型返回可在整个应用程序中使用的通用属性。
我的部分应用程序跟踪网站的响应时间(首字节时间/TTFB)。在我的Website 模型中,我将响应时间“评分”为“好”、“差”和“平均”。所以,我有一个返回这个的访问器。很简单,很好的做法:
/**
* Accessor for TTFB grade (good, bad, average).
*
* @return String
*/
public function getAverageTtfbGradeAttribute()
{
if($this->average_ttfb < 0.5) {
$grade = 'good';
} elseif($this->average_ttfb >= 0.5 && $this->average_ttfb < 1.2) {
$grade = 'average';
} else {
$grade = 'bad';
}
return $grade;
}
我想在整个应用程序中显示 TTFB/响应时间,但我希望它根据成绩着色。我创建了另一个依赖于第一个访问器的访问器:
/**
* Accessor for TTFB with a colour
*
* @return String
*/
public function getAverageTtfbColoredAttribute()
{
$str = '<span class="';
if($this->averageTtfbGrade == 'good') {
$str.= 'text-success';
} elseif($this->averageTtfbGrade == 'average') {
$str.= 'text-warning';
} else {
$str.= 'text-danger';
}
$str.= '">' . $this->average_ttfb .'s</span>';
return $str;
}
要使用它,我只需要使用$website->averageTtfbColored。效果很好。
我的问题是,这是好还是坏的做法?我的理解是,无论是在控制器、模型还是应用程序的任何其他部分中,HTML 都不应该成为业务逻辑的一部分。但是,如果我遵循这个逻辑,那么我最终会在视图中使用 if 语句,这些语句将在我的应用程序的许多地方重复 - 这违反了 DRY 原则。
这里的最佳做法是什么?我是不是想多了?
【问题讨论】:
-
逻辑是写在控制器中的,模型负责数据检索和大写字符串等基本操作。视图应该以最少的 if 条件显示数据。这是我遵循的模式,不知道是不是你所期望的。
-
这就是胖控制器、瘦模型之间的区别,反之亦然。这不是真正的问题。我可以将这个逻辑从模型移动到控制器,但是问题已经从视图移动到控制器,然后我有 2 个问题;控制器中的 HTML 并且重复了很多次。有了我现在所拥有的,我在一个模型中就有了这个逻辑,它在整个应用程序中都使用了,但只写了一次。唯一的缺点是它包含 HTML,这通常是禁忌。我想真正的问题是这个用例是否是一个可接受的例外
-
@ImmortalDude 我不同意你的观点。模型层(与 MVC 中的模型相反)应该包含业务逻辑,视图层应该处理表示,控制器尽可能瘦。胖控制器是一种常见的反模式,它使应用程序难以维护和测试。
-
@MatthewDaly
as opposed to models in MVC我正在遵循那个确切的模式,我不反对你的模式,只是我遵循你不遵循的模式,只是我的意见,并不难以 mvc 模式编写代码的核心“方式” -
@ImmortalDude 模型层与框架提供的模型类不同,例如 Eloquent。 MVC 中的 M 不仅包含 Eloquent 之类的东西,还包含任何其他业务逻辑,例如,如果您的应用程序发送推送通知,则该功能应该包装在服务类中。将这种功能转移到控制器是导致难以测试的臃肿、重复代码的秘诀,并且在过去一直困扰着我。如果控制器方法的长度超过 10 行左右,则应始终考虑将部分功能移至模型层。