MVC:在模型中拥有静态方法


MVC: Having static method in models

简体:如何避免在模型中使用静态方法?

Loquacious:假设我有一个用户类。有了userID,我可以通过(new user($userID))->getUserName()获得用户名。好吧,如果我想查找用户呢?(new user())->lookup($uname, $pass)。仍然很好,但后一种情况可以通过一个简单的静态方法user::lookup($uname, $pass)来完成!
一些想法:

  • 没关系!随时使用(new object())->method()。那么我应该创建一个空对象来调用函数吗?
  • 将此函数移出模型。如果它需要数据库查找,哪里比模型上下文更好?
  • 定义为静态方法。那么,在一个类中混合使用公共方法和静态方法不是很蹩脚吗?

旁注:我已经搜索了这个问题,没有效果!

将此函数移出模型。如果它需要数据库查找,哪里比模型上下文更好?

是的,的确,这是解决问题的最好办法。

目前你的User类违反了单一责任原则,基本上是说"一个任务-一个类"。

现在你的User描述用户实体/状态并处理持久性(在你的情况下-从数据库检索)。看,有两件事。

我建议你创建另一个类来处理持久化任务,比如添加/更新/删除用户。最简单的解决方案是创建一个原始存储库,如下所示:

<?php
class UserRepository
{
    public function addUser(User $user);
    public function updateUser(User $user);
    public function deleteUser(User $user);
    public function getUserById($id);
}

则可以按以下方式检索用户:

// get an instance of this repository class
$userRepository  = new UserRepository;
// ask it to find and return user from the database by ID
$user = $userRepository->getUserById($_GET['id']);

易于阅读,易于操作,对吗?

这个UserRepository类实际上是存储库模式的原语实现。UserRepository模拟所有用户的内存集合,将实现隐藏在其中。它对作为用户的你隐藏了实际的持久化机制:想象一下,你的同事会写这个类,而你只是使用它的方法,比如UserRepository::getById(1)——你甚至不知道/关心它是否从文件/db/API中抓取数据。这很好。)

这个特殊的实现在Kristopher Wilson的书"The Clean Architecture in PHP"中有非常清晰的描述,我强烈推荐你阅读:它将花费你两到三个晚上,并将你推向一个新的水平。

当然,你可以扩展方法列表,添加查找等等。

class UserRepository
{
    public function getByCompany(Company $company);
    public function getByEmail($email);
    public function countTotal();
}

事实上,每次你需要在数据库中抓取/添加/更新用户,你应该通过这个存储库来做。

我想强调这是模式的一个简单实现,特别是,如果您将它与Martin Fowler所描述的Repository进行比较的话。但是,在大多数情况下,这是完全可以的。

  • 没关系!随时使用(new object())->method()。那么我应该创建一个空对象来调用函数吗?

    取决于创建实例的成本

  • 将此函数移出模型

    这里我想到的是

    工厂模式。

    指出:

    当第一次调用中的$userID不存在时会发生什么?

    难道你的lookup()方法没有在一次调用中创建2个实例,首先用于查找,其次是返回的找到的一个?

例如,一个factoryppattern可以有findByID()findByName()并返回一个UserObject。所有这些都不应该依赖于这个语法:(new object())->method(),这很好,但并不总是最佳实践。