Traits个
是另一种继承方法,它解决了PHP
使用的单个类继承的一些限制.这通常用于在模型之间共享类似的逻辑.让我们假设有几个模特与公司有关系.
trait HasCompany {
public function company() {
return $this->belongsTo(Company::class);
}
}
Now the user can easily share code from the trait, by the keyword using
. This is an example and most often a more complex use case would be needed for it to make sense.
class User {
use HasCompany;
}
Repositories
Repositories is a design pattern to abstract data layers from the application. Your logic should not care about how you store data, so if you wanted to change from Mysql
to Mongodb
, you would only swap out the repository and not have to change business logic.
这里非常固执己见,但这不是适合Laravel
人的设计模式.Laravel
具有Eloquent 的功能,因此数据库层已经被抽象.存储库有时用于Laravel
个应用程序,但不是一个常见的场景,而是一个异常值.存储库的主要原因之一是数据实现不可知,它已经存在,并且可以在SQL服务器之间完美地交换.还有Eloquents
个特性,比如::find()
、scopes
等,感觉像是存储库的替代品,同时使用起来很奇怪.
If you use Doctrine as the ORM
, which you can in Laravel
, it is the core of their architecture and should be used.
Services
Is commonly used for a place to store business logic or the building blocks of your actions in your application. In traditional MVC
design, Controllers should only handle input. Normally you would put your logic in Models, but they get "fat" very quickly, when this happens services is a common place to put business logic. Sometimes also named actions or commands, which is similar but a little bit different approaches.
One of the core things it solves, is to make your business logic reusable. Imaging filtering all users by an active flag, when you retrieve it in its controller.
public function all() {
return User::where('active', true)->get();
}
现在您有了业务逻辑,它强制您只处理活动用户,之后您希望通过使用命令通知所有活动用户,并通过邮箱通知所有活动用户.
class NotifyUsers extends Command {
public function handle() {
foreach (User::where('active', true)->get() as $user) {
$user->notify();
}
}
}
现在,您必须手动更新业务逻辑.下次添加第二个条件或更改逻辑时,必须在两个地方更改代码.在经常使用此代码块的大型应用程序中,如果不忘记其中一个位置,则很难维护这些条件.如果使用此逻辑创建服务,则可以轻松地在整个应用程序中使用相同的业务逻辑.虽然只有一个地方可以修改代码,但如果这种逻辑必须改变的话.
class UserService {
public function all() {
return User::where('active', true)->get();
}
}
在您希望使用此业务逻辑获取活动用户的任何地方,您都可以使用该服务.因此,只有一个地方来维持逻辑.一个呼叫可以简单到resolve(UserService::class)->all()
.服务的更新逻辑示例如下.
// controller
public function all(UserService $userService) {
return $userService->all();
}
// command
class NotifyUsers extends Command {
public function handle(UserService $userService) {
$userService->all()->each->notify();
}
}
Conclusion
世界不是黑白的,你必须想出自己的方法.我的建议是,不要把时间花在存储库上,Laravel
有很多特性来处理与数据相关的操作scopes
、getters
、setters
等,这些都与存储库设计模式相冲突.看看类似服务的设计方法是否适合您,您是否可以利用em.Traits
与其说是一种体系 struct 设计模式,不如说是一种类继承替代方案,只是为了在类之间共享逻辑.