我使用Eloquent来实现我的模型。它有很多方法可以使模型的使用变得更加容易。但是,在某些情况下,我必须实现访问数据库的功能,但不返回Eloquent模型。
例如,想象一下常见的用户模型。 Eloquent在用户模型的CRUD操作中为我提供了很多帮助,但如果我必须实现一个返回用户统计信息的方法(例如,总用户数,活跃用户数等),那该怎么办呢。
我应该在哪里实现此功能?在Eloquent模型中,作为public static
函数(例如User::getStats()
),或者应该有一个不同的类。
在Eloquent模型上使用这些方法似乎有点不自然,因为它们不是雄辩相关的。
答案 0 :(得分:2)
这完全取决于你,但决定一个约定并坚持下去是个好主意。
我的经验法则是:
如果它与通常由Eloquent模型表示的单个项目相关,则将其作为该模型上的公共静态方法。例如,在我当前的项目中,我有一个Contract
模型。我需要一种方法来为新合同生成合同ID字符串(与遗留系统兼容)。这与单个项目(合同)有关,但由于技术原因需要与Eloquent模型分开生成(即,它基于具有不同连接的单独数据库)。所以我创建了一个公共静态方法:public static function generateContractIdentifier($id, $salesRep)
。如果您使用存储库访问数据库,可以将其放在那里。
如果它更通用(即没有绑定到Eloquent模型的实例),我将它放入一个单独的库中。例如,在同一个应用程序中,我有一个用于处理打印项目的队列(工业过程)。该应用程序有一个仪表板,我需要显示管理的当前队列状态。为此,我创建了一个ProcessStatus
库并实现了一个方法:public function getStatus()
,它运行查询并将结果作为数组提供给视图中显示。这与队列中的任何特定项目无关,因此我将其放在单独的库中。
答案 1 :(得分:1)
与往常一样,这取决于您的项目以及用户在其中扮演的角色。
但基本上,不,我不认为构建报告的逻辑属于用户模型。虽然它可能与用户有关,但是对于SOLID原则,User类应该只有一个责任,在这种情况下是处理User实体。
这包含实例的获取和设置属性,在一个简单的项目中,它可能也可以在模型上定义一些范围,例如:仅选择活跃用户,例如User::getActive();
但随着项目的增长,您应该考虑使用更具体的类。
例如,您可以将Eloquent功能抽象为User-Repository。所以现在你有了一个处理权限的操作处理程序,比如
$userRepo->getAll();
$userRepo->getActive();
$userRepo->getInactive();
和User实例的处理程序:
$user->getName();
$user->setStatus();
创建报告和统计数据是一个完全不同的主题。所以你可能有类似UserReportBuilder
oder UserStatisticsService
的东西:
$userStats->getMostActive();
$userStats->getRegistrationsPerDay();
一个简单的例子:
// UserRepository:
class UserRepository
{
protected $model = $model;
public function __construct($model)
{
// you pass in an instance of the actual Eloquent model
// so you have the whole power of eloquent in here
$this->model = $model;
}
public function getActive()
{
// this returns a collection of models
return $this->model->where('status', 'active')->get();
}
}
$userRepo = new UserRepo(new User);
这就是它。您仍然可以使用Eloquent,但您已将部分功能与clewar职责分开。因此,您的UserStats类只能用于构建用户统计信息:
class UserStats
{
// You could pass in the Repository through the constructor
// or just use the Eloquent model directly
public function getRegistrationsPerDay()
{
return User::groupBy('day')->get(
[
DB::raw('DATE(created_at) as day'),
DB::raw('count(*) as registration_count')
]
);
}
}
User实例或UserStats构建器不需要知道如何获取所有用户,而User实例或UserRepository不需要知道如何计算每天的注册数,因此将该功能拆分为单独的,独立的部分,只做一件事。
我认为你明白这一点,我希望它有意义。也许你应该让自己更熟悉SOLID-principles,并在遇到类似问题时尽量记住它们。