使用 Laravel Eloquent 修改器时要小心点
我承认 – 在使用 Laravel 框架工作的五年中, 我沉迷于它的 “magic”, 编写很少的代码就可以实现一个功能. 但是最近, 随着我项目规模的扩大, 这种“magic”开始成为问题. 典型的一个例子是 Eloquent Accessors, 因此在本文中, 我将反对使用他们, 以及说明如何替代它们.
访问器如何工作以及它们为什么很棒
让我们记住, 访问器时如何工作的.想象一下,在 users 数据库表中,您有 name 和 surname 列, 但是您希望展示 full name 。但是你并不想每次将字符串连接在一起, 因此访问器是一个很棒的解决方案!
你只需要在 app/User.php 中定义:
public function getFullNameAttribute()
{
return $this->name . ' ' . $this->surname;
}
然后, 只要有 $user 对象, 你就可以这样写, 例如, 在 Blade 中:
{{ $user->full_name }}
Eloquent 将负责调用此方法, 还将蛇形属性 full_name 转换为 getFullNameAttribute 驼峰方法. 魔法, 难道不是吗?
问题 1: 此字段是什么?
问题通常发生在大项目和大团队中, 当代码被别人接管时.
例如, 当您的数据表或其它位置有很多字段, 你不能够明确的知道某些字段是访问器. 例如, 如果你看到 $user->full_name 和 $user->home_address , 某些人可能会真的认为它们是数据库里的字段, 对吗?
因此, 访问器影响了代码的可阅读性. 如果一个初级开发者 (或者不熟悉 Laravel 的人) 依据这部分代码进行开发 – 可能需要很长的时间去理解, 为什么这个字段不在数据库中, 并且他们可能花几分钟/几小时来挖掘过去的迁移, 寻找 full_name 列.
此外, 这些字段在 IDE 中是 “不可点击的”, 因此你很难寻找方法内隐藏了什么. 为了查找 “getFullName”, 你需要在你的 IDE (例如 PhpStorm) 中搜索整个项目 (或者模型文件) .
问题 2: 大访问器可能 "隐藏" bug
这里我们有个简单的拼接字符串的例子. 但是我确实经常看到访问器作为成熟的计算方法有超过 20 行的逻辑代码.
想象一下对于国际姓名来说 full_name 可能有更大的逻辑 – 在一些国家中姓名分为 3 个部分, 还有可能包括 “Mr/Mrs/Ms”, 缩写, 大写/小写字母等等. 尽管它仍然有效,但是在这种大逻辑中很可能会出现错误。
而且几乎没有人会为 访问器 编写自动化测试. 如果您看了 code structure point of view, 像这样大的计算逻辑应该写在 Service 层的类中, 这样就可以更方便的进行单元测试.
解决方案: 只需使用“ Getter”方法
那么,如何避免过多的“Magic”呢?简单 – 使用方法就好,而无需任何转换。
因此, 在 Blade 中使用 {{ $user->getFullName() }} 替代 {{ $user->full_name }} 难道不更具有可读性吗?
首先, 可以立刻明白它并不是数据库的一列 – 因为末尾有 () , 很显然这是 方法. 同时, 您的 IDE 将允许点击它, 将方法放入您的模型中. 难道不更容易导航吗?
在模型中,只需将 getFullNameAttribute() 重命名为 getFullName() :
public function getFullName()
{
return $this->name . ' ' . $this->surname;
}
你同意吗? 您是否曾经在Laravel中遇到过“Magic 过多”的问题 - 使用了访问器或其他魔术方法?
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
api就不能用方法
@sinofaneliu 倒是也可以使用, 无非就是 自己手动写 .
按照文章所说, 这样:
但是我觉得这样不太好, 如果用到的地方多, 容易书写出错. 如果字段名 (full_name) 变了 改起来也不方便. 或者 你在Laravel 中使用 Resource , 但是在 lumen 中怎么办? 只能是自己封装一下.
这样就直接调用就可以了.