我是不是正确实施了我的 DAO?
Posted
技术标签:
【中文标题】我是不是正确实施了我的 DAO?【英文标题】:Am I implementing my DAO's correctly?我是否正确实施了我的 DAO? 【发布时间】:2012-09-02 13:03:07 【问题描述】:我将在这里大大缩短实际代码,以使其更快。我已经拿出了大量的支票和其他东西,只是为了让它更容易理解。
这是我的用户类:
class User
private $userId;
private $userDAO;
public function __construct($dbh, $userId)
$this->userId = (int) $userId;
//Create the UserDAO object
$this->userDAO = new UserDAO($dbh, $this);
//Get the up to date details of the user
$userData = $this->userDAO->getUserData()
这是我的 UserDAO 类:
class UserDAO
private $dbh;
private $user;
public function __construct($dbh, $user)
$this->dbh = $dbh;
$this->user = $user;
public function getUserData()
$stmt = $this->dbh->prepare("SELECT username FROM " . USERS_TABLE . " WHERE userId = :userId LIMIT 1");
$stmt->bindParam(':userId', $this->user->getUserId(), PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
这是正确的方法吗?如您所见,DAO 从 User 类的实例中获取用于数据库查询的变量,因此 DAO 方法不需要任何争论。
我的 getUserData() 方法是否应该对 userId 有争论并使用提供的 userId 来获取用户数据,以便 DAO 对象在每次需要获取用户数据时都不需要依赖 User 类的实例,因为可以在方法签名中提供任何 userId 吗?
谢谢。
【问题讨论】:
【参考方案1】:提供 User 类的对象称为“依赖注入”——有点。从我的角度来看,这实际上是一个很好的方法。这样,您就可以将其留给 UserDAO 类来决定将哪些数据用于查询。
虽然我会使用 $user 作为 getUserData 函数的参数,而不是通过构造函数 - 但这可能只是我个人的偏好。
【讨论】:
我在想,如果在另一个类中通过一些随机方法我检索了一个 userId 并需要获取一些用户详细信息,该怎么办。我必须创建一个 User 对象,然后创建 UserDAO 并获取数据,将其设置在 User 对象中,然后我将访问它。我在想,当我可以在 getUserData() 方法中放入 userId 参数时,工作量太大了,这样可以更快地检索数据而无需创建 User 对象。我只是想也许 UserDAO 方法不应该在 User 类的实例中工作并且是静态方法? 当然你是对的,有时只传递用户 id 会更轻量级,但不一定是最好或最优雅的。考虑以下事项:当传递用户对象时,您在 dao 中的查询中使用哪些值并不重要,因此无论您在 dao 中进行什么更改,只要数据包含在用户对象中,它就会起作用,并且除了 UserDAO 之外,您不必更改代码 - 但如果您只传递 id 并且突然在查询中需要用户名,则必须更改该方法的每次调用并传递用户名而不是 id。 如果您对有关依赖注入的更多信息感兴趣:Fabien Potencier 写了一篇关于它的有趣文章:fabien.potencier.org/article/11/what-is-dependency-injection(然而,他们在 symfony2 框架中使用的方法有些偏颇 - 仍然不过很好)【参考方案2】:我看到 User 和 UserDAO 是紧密耦合的。用户拥有 UserDAO,而 UserDAO 拥有 User 类。
在 DAO 设计模式中,它的 DAO 提供域对象或传输对象。
我认为更好的方法是从 User 类中删除 UserDAO,然后将 User 对象传递给 UserDAO 类以执行必要的操作。
【讨论】:
但是我不是每次想要做数据库工作时都必须创建一个新的 UserDAO 对象吗?当我在 User 方法中创建 UserDAO 对象,然后该方法调用 User 类中的另一个方法并且需要做一些数据库工作时,我是否必须再次在该方法中重新创建 UserDAO 对象,除非已经创建的 UserDAO对象在其签名中传递给它?还是我误会了你? 有两种方法可以使它变得更好。你介绍了 Factory 类,它将创建你的 DAO 对象。在工厂中,您可以决定是否要为每个请求保留一次实例、实例池或新实例。除此之外,您的 DAO 对象必须由业务层(也称为服务层)使用。所以要对 User 对象进行任何操作,你的服务或业务层都应该调用 DAO 对 User 进行操作。以上是关于我是不是正确实施了我的 DAO?的主要内容,如果未能解决你的问题,请参考以下文章