I’m trying to improve my implementation of active record to make it easier for unit testing. So far I have done this to update a row, a classic example:
$account = AccountPeer::getByPK(12);
$account->access_date = time();
$account->save();
The problem with this is that the $account data object has dependency on the database in order to perform the save operation and the dependency is not injected but looked for. Additionally, the class needs to extend a base class with methods that do the actual insert/update. I have found an article The Problem With Active Record that explains the problem in detail and suggests a solution. So now I have converted the logic and I do this:
$accountTable = new AccountTable($db); // (I may use DI in the future instead of new, but this is not important now)
$account = $accountTable->getByPK(12);
$account->access_date = time();
$accountTable->save($account);
Now the row data object ($account) is kept separate from the table object ($accountTable), I pass the database dependency to the table object and all is fine - at least to me this is a good separation according to this article by Miško Hevery - the data object is holding pure data and does not need any dependencies.
But now I want to add more features to get related objects from $account. Suppose each account belongs to a user so I may want to get the user. This is the most logical way to me:
$accountTable = new AccountTable($db);
$account = $accountTable->getByPK(12);
// $user is supposed to be an object corresponding to a row in the user table
$user = $account->getUser();
As you can see the account object needs to retrieve the user object. In order to do this it needs to contact the database but how can it do it if it has no knowledge of a database? I could do this:
$user = $account->getUser($db);
but it looks hackish. What would be the best way to achieve this? Should I break the principle of having a pure data object and inject database dependency into it? What would the getUser() method look like?
class Account {
public function getUser() {
$userTable = new UserTable($db);
$user = $userTable->getByPK($this->user_id);
return $user;
}
}
as you can see I need the $db object here, how do I pass it in?