5

我一直在研究和阅读很多关于在 PHP 中使用单独的层来创建可维护和可读的代码。但是,我看到很多代码将实体和数据库访问放在一个类中。例如:

class User{
     public $id;
     public $username;
     public $database;

     function add(){
           $database->query ....
     }
}

我觉得这很奇怪,因为在这里您将 User 类与数据库元素混合在一起,这使得维护变得更加困难。

我喜欢这样工作:

  • 一个单独的数据库类
  • 一个用户类
  • 用户数据类

这像这样工作:

$database = new Database();
$database->openConnection();
$dataUser = new DataUser($db);
$user = new User(1,"myname");
$dataUser->saveUser($user);

所以我想知道,我是以正确的方式工作还是第一种方式是创建代码的更好方式?我发现可能非常容易维护,因为您有一个单独的实体和一个单独的数据库类来处理数据库操作。

4

3 回答 3

2

我做什么 :

我的模型不是链接到数据库的实体(当我不使用学说时),所以没有“活动记录”方法。一个对象不知道如何获取它的依赖项(例如,一个用户可能有 n 条评论,我的模型不知道如何获取评论)。

class User{
private $name;
private $password;
// getter and setters
}

我的服务包含一些可以从提供者那里获取模型的业务逻辑,一个服务可以有很多提供者。

class UserService{
    function __construct(IUserProvider $userProvider){
        $this->userProvider = $userProvider
    }
    function getUsers(){
       // return an array of user objects
       return $this->userProvider->getUsers();

    }
}

最后,我有一个数据提供者,它知道如何从数据库、文本文件、json 文件、网络服务请求数据:

 class UserProvider implements IUserProvider{
      function __construct(Connection $connection){
         $this->connection = $connection;
      }
      function getUsers(){
         return $this->toUsers($this->connection->fetchAssoc("Select * from users"));
      }
      function toUsers(array $datas){
          // convert user records to an array of User
          (...)
          return $users;
      }
 }

然后界面

interface IUserProvider{
     /**@return array an array of User */
     function getUsers();
}

如果我需要获取用户评论,那么我的评论服务知道如何从用户 ID 获取评论。因此,要获取用户及其评论,我需要 2 个对数据库的请求。一个来自 UserProvider ,另一个来自 CommentProvider。

所以我有 3 层:

  • 我的应用层(显示用户,响应任何请求......)
  • 我的服务层(它必须使用命令行界面并且不知道我的 Web 应用程序,除了通常绑定到我使用的框架的密码编码和 ACL 的东西可能......)
  • 我的数据访问层对其他层一无所知,

我的层通信的唯一方式是通过我从层传递到层的模型。

而且我所有的类都是用依赖注入容器构建的,所以接线不是问题。

这是我制作的应用程序示例,它是开源的:https ://github.com/Mparaiso/silex-bookmarkly

欢迎任何想法。

于 2013-03-18T09:29:48.970 回答
1

就个人而言,我认为抽象可能是矫枉过正UserDataUser因为,在这种情况下,UserData可能与ProductDataexample 非常相似 - 它们仍将包含add($data)find($id)

在您的情况下,它是MVCUser方法中的一个模型,包含数据库存储/检索逻辑是完全可以接受的。但是,您可能会发现,您在该类中重新创建了与其他模型中相同的 DB 方法。这是您可以开始查看ORM实现的地方。因此,常见的 DB 访问方法是在一个抽象类中定义的,然后您的所有模型都会根据需要进行扩展和覆盖。User

于 2013-03-18T09:06:45.213 回答
1

易于维护,因为您有一个单独的实体和一个单独的数据库类

您似乎是在说您希望从Active Record方法转移到Data Mapper/Entity/Repository方法。这是一个很好的前进方向,因为它采用了更好的关注点分离。你可以自己构建它,但你可能想看看像Doctrine这样的解决方案,它允许你按照以下方式做一些事情:

$product = new Product();
$product->setName($newProductName);
$entityManager->persist($product);

$product实体只是一个包含记录数据的 POPO(普通旧 PHP 对象),不知道它是如何持久化的,当需要持久化时,它被传递到实体管理器以处理存储。

于 2013-03-18T09:16:46.540 回答