哪里放不是Eloquent相关的SQL查询

时间:2014-06-30 19:09:05

标签: php laravel orm eloquent

我使用Eloquent来实现我的模型。它有很多方法可以使模型的使用变得更加容易。但是,在某些情况下,我必须实现访问数据库的功能,但不返回Eloquent模型。

例如,想象一下常见的用户模型。 Eloquent在用户模型的CRUD操作中为我提供了很多帮助,但如果我必须实现一个返回用户统计信息的方法(例如,总用户数,活跃用户数等),那该怎么办呢。

我应该在哪里实现此功能?在Eloquent模型中,作为public static函数(例如User::getStats()),或者应该有一个不同的类。

在Eloquent模型上使用这些方法似乎有点不自然,因为它们不是雄辩相关的。

2 个答案:

答案 0 :(得分:2)

这完全取决于你,但决定一个约定并坚持下去是个好主意。

我的经验法则是:

  1. 如果它与通常由Eloquent模型表示的单个项目相关,则将其作为该模型上的公共静态方法。例如,在我当前的项目中,我有一个Contract模型。我需要一种方法来为新合同生成合同ID字符串(与遗留系统兼容)。这与单个项目(合同)有关,但由于技术原因需要与Eloquent模型分开生成(即,它基于具有不同连接的单独数据库)。所以我创建了一个公共静态方法:public static function generateContractIdentifier($id, $salesRep)。如果您使用存储库访问数据库,可以将其放在那里。

  2. 如果它更通用(即没有绑定到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,并在遇到类似问题时尽量记住它们。