尝试使用类型约束来优化你的 Laravel 模型
在最近的几个项目中,我们对Eloquent模型做了一些小的改动,并发现了一些巨大的价值。我想和大家分享一下,以使他人也能和我们一样从中受益 🚀
让我们首先为一个想象中的电子商务商店建立一个产品模型:
php artisan make:model Product
现在我们在App命名空间下有了全新的Product模型:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
//
}
我们在开始时做一些初始化设置:
- 强制使用严格类型模式
- 标记类为final
- 添加逻辑代码段
...结果如下:
<?php
declare(strict_types=1);
namespace App;
use Illuminate\Database\Eloquent\Model;
final class Product extends Model
{
#-----------------------------------------------------------------
# Class Constants
#-----------------------------------------------------------------
//
#-----------------------------------------------------------------
# Class Properties
#-----------------------------------------------------------------
//
#-----------------------------------------------------------------
# Relationships
#-----------------------------------------------------------------
//
#-----------------------------------------------------------------
# Accessors and Mutators
#-----------------------------------------------------------------
//
}
接下来,我们将遵循一些有关表和主键名的一般团队约定进行设置,并包含必要的关联代码:
<?php
//
final class Product extends Model
{
//
#-----------------------------------------------------------------
# Properties
#-----------------------------------------------------------------
/**
* @var string
*/
protected $table = 'products';
/**
* @var string
*/
protected $primaryKey = 'product_id';
#-----------------------------------------------------------------
# Relationships
#-----------------------------------------------------------------
/**
* @return HasOne
*/
public function currency(): HasOne
{
return $this->hasOne(Currency::class, 'currencyCode', 'currency');
}
//
}
你可能想知道这当中有什么不一样,这就是标准的Laravel-你完全正确。我包括了这些细节,是为了确保新手也能够跟进 😌
在这个阶段,我们将自己风格的访问器和修改器引入到模型中(大家熟知的getters/setters):
<?php
//
final class Product extends Model
{
//
#-----------------------------------------------------------------
# Accessors and Mutators
#-----------------------------------------------------------------
/**
* @return string
*/
public function getName(): string
{
return $this->getAttribute('name');
}
/**
* @param string $name
*/
public function setName(string $name): void
{
$this->setAttribute('name', $name);
}
/**
* @return float|null
*/
public function getPrice(): ?float
{
return $this->getAttribute('price');
}
/**
* @param float|null $value
*/
public function setPrice(?float $value): void
{
$this->setAttribute('price', $value);
}
/**
* @return bool
*/
public function isActive(): bool
{
return $this->getAttribute('is_active');
}
//
}
这很简单,但是您可能想知道详细细节以及为什么要手工编写这些方法。
有什么优点?
自从介绍了这种编码风格以来,我们已经看到了这些好处:
- 模型划分逻辑部分,因此易于查找代码
- IDE自动提示模型属性
- 因为使用严格类型的功能,所以模型属性带有类型提示
- 保留了 Eloquent 的功能,不会任何骇人的重写操作
在我们的团队中,由于这些微小的变化,我们发现开发人员的经验有了整体改善。使用其他人的代码时,错误更少,代码理解得到改善,学习成本降低。
为什么不仅仅使用公共属性?
当我向任何人展示此问题时,自然会出现一个问题:为什么不仅仅使用公共属性?好吧,我认为这会带来一些限制:
-
无法强制限制给定属性的数据类型,可以将浮点值赋值给int 型的数据库属性
-
无法确定给定属性的返回类型,因此在语言级别上,您不知道状态字段是否应返回字符串或整数
-
属性级别的数据验证很困难,您可以为明显无效的属性设置一个负值(例如:产品的负价)
-
如果更改了属性列名称,则需要在访问该属性的所有位置手动进行该更改;由于属性是动态的,因此无法利用 IDE 使用情况搜索
结束语
您可能想尝试一下,看看是否有任何好处。这在很大程度上有利于 PHP 7 的强类型化,因此对此优先考虑的团队将获得最大的收益。最后,您的想法可能会有所不同🙂
在Twitter上与我分享您的想法和想法!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: