I’ve been trying to get a firm understanding of the MVC design pattern so that I can write my own framework for implementing the back-end of a forum web application using Slim 3. In particular, after reading this, and asking this and this question myself I’m now at a point where I think I understand how the model should be a layer composed of data mappers, services and domain objects. However I have some more questions regarding domain objects.
At the moment with a very similar structure from an answer given to this question I asked. I have a basic model layer structure for registering a user to my forum application. However it seems to me that my User ‘domain object’ isn’t really doing anything at the moment, it only has getters and setters and I could probably do without it.
User domain object:
class User
{
private $id;
private $email;
private $username;
private $password;
public function __construct(Email $email, Username $username, Password $password)
{
$this->email = $email;
$this->username = $username;
$this->password = $password;
}
public function getId()
{
return $this->id;
}
public function setId(int $id)
{
$this->id = $id;
}
public function getEmail()
{
return $this->email;
}
public function setEmail(Email $email)
{
$this->email = $email;
}
public function getUsername()
{
return $this->username;
}
public function setUsername(Username $username)
{
$this->username = $username;
}
public function getPassword()
{
return $this->password;
}
public function setPassword(Password $password)
{
$this->password = $password;
}
}
This user domain object directly mirrors that of my ‘user’ SQL table that is populated when a user registers. In fact this created user domain object is passed to my data mapper then the fields of the passed in user object are extracted and inserted into the database.
Inserting a user object into my ‘user’ table:
private function insertUser(User $user)
{
$sql = 'INSERT INTO users (email, username, password)
VALUES (:email, :username, :password)';
$statement = $this->connection->prepare($sql);
$statement->execute([':email' => $user->getEmail(),
':username' => $user->getUsername(),
':password' => $user->getPassword()]);
$user->setId($this->connection->lastInsertId());
return $user;
}
Could I not just directly pass in the strings that the user typed into the form (after validation and sanitation) instead of having to create this user domain object. It just seems unnecessary at the moment.
This is where I’m confused as to what exactly a domain object should be. I understand they should encompass business logic, but identifying what business logic I would need for a forum application is proving difficult. For example I would like each user to have their own profile page that is publicly visible, that they can only edit and update when the user in question is logged in.
Would I need to create a ‘profile’ domain object together with a new profile table that links to my original user table and user domain object? Or could I simply extend my existing user table and user domain object to have properties and methods that can allow a user to display and update their profile?
I understand this is a matter of design and can be subjective, but some advice on what should be in a domain object (especially for the previous example with a profile) and if they need to marry up to a table or not would be helpful.
A lot of the tutorials I see such as this, simply have a single model object that has data mappers methods in them which doesn’t seem right. A lot of tutorials also use frameworks that utilise ORM which is something I’m trying to avoid using as I want to write everything from scratch, although I’m fine with using Slim 3 / 4 PHP.