I'm going to take the example of a user
object. A user needs to be registered, logged in, logged out, edited (e.g., email change), etc.
So on one hand I have a user
object, which includes a variety of class variables (pseudo, email, etc) along with getters and setters and maybe some functions that do not deal with the db.
On the other I have a DAO
class which is the object that directly deals with the database through a variety of MySQL / PDO queries (create record, update, retrieve info, etc).
Is there any reason to not have the user
object interact directly with the DAO
object? In other words, when the Controller
request a database query relating to an existing user
instance (e.g., during the registration process), should it simply call a function in user
which itself calls a function in DAO
, or should there be a layer in between?
I have seen examples where the controller calls a 3rd class to interact with the DAO, and passes a user
instance as an arg. Sometimes instead, this third layer is in charge with creating the user
instance and dealing with the DAO
. It seems to me that all the functions used to deal with the DAO
could reside inside the user
object. What am I missing?
If you are adhering to MVC design pattern, then there is not reason for the User
instance to be in the controller. It should be part of model layer, instead of leaking over to presentation layer.
It seems that what you call "controller" is actually more of a service, which should be a part of the model layer, that handles the interaction between domain objects on the data storage related structures (mappers, repositories, DAOs).
Basically, what you are missing is correct separation of concerns.
The controller should be just passing the data to recognition or some user management service, instead of dealing with domain business logic. Said service should initialize the User
object, validate the data and try to save it. Controller should no be aware of any of this.
Something like this:
class SomeController
{
// ---- snip ----
public function postRegister( $request )
{
$accounts = $this->serviceFactory->create('AccountManagement');
$account->create( $request->getPost('username'),
$request->getPost('email'),
$request->getPost('password'),
$request->getPost('password2') );
$this->view->setState( View::STATE_POST );
}
// ---- snip ----
}
class AccountManagement extends Service
{
// ---- snip ----
public function addUser( $username, $email, $password, $repeated_password )
{
$user = $this->domainObjectFactory->create( 'User' );
$user->setNickname( $username );
$user->setEmail( $email );
$user->setPassword( $password );
$user->matchRepeatedPassword( $repeated_password );
if ( $user->isValid() )
{
$dao = $this->DAOFactory->create( 'User' );
$dao->save( $user );
}
// additional code for saving the error state
// if domain object turns out to be invalid
// or DAO returns an error
}
// ---- snip ----
}
P.S. you might find this post relevant.
I think you’re describing some sort of adapter or gateway for models, where you have a class that calls an adapter (it may interact with a database, or an XML data source) and then assigns the results to instances of your model (i.e. assigns each matching user result to an instance of your User
model).
In the past, I’ve taken the approach you’ve described where you have models that represent one item, and then a DAO to save and retrieve these items to a data source (be it a database or whatever), and the controller that does the logic. So an extremely basic version:
UsersDAO.php
class UsersDAO extends DAO
{
public function save(User $user)
{
return is_null($user->id) ? $this->insert($user)
: $this->update($user);
}
public function insert(User $user)
{
$sql = "INSERT INTO `users` (`username`, `password`)
VALUES (:username, :password)";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':username', $user->username);
$stmt->bindParam(':password', $user->password);
$stmt->execute();
}
}
User.php
class User
{
public $id;
public $username;
public $password;
public $email;
}
UsersController.php
class UserController extends Controller
{
public function register()
{
$usersDao = new UserDAO;
if ($_POST) {
$user = new User;
$user->username = $_POST['username'];
$user->password = $_POST['password'];
$userDao->save($user);
}
}
}
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With