I have a database with 3 tables. person, player, and coach. The person table contains things that the player and coach have in common, such as firstName, lastName, and email. The player, and coach tables then have a link back to the person table with a personId field. Every person who accesses the site has a person entry. Additionally, some users may also have player or coach entries. The database is set up this way to maintain normalization.
In my code, I have a person, player, and coach class. The player and coach inherit from person. Below is a truncated version of the person and player classes.
class person{
private $firstName;
private $lastName;
public function __construct($firstName, $lastName){
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class player extends person{
private $position;
private $jersey;
public function __construct($firstName, $lastName, $position, $jersey){
parent::__construct($firstName, $lastName);
$this->position = $position;
$this->jersey = $jersey;
}
}
As a heads up I’m quite new to OOP so bear with me if there’s things I don’t know.
(side question, what are the above classes considered, Views?)
Now in order to populate these I use what I understand to be the Model classes (is that right?).
class personModel{
public function getPerson($personId){
$sql = "SELECT * FROM `person` WHERE `personId` = '$personId'";
//skipping some sql stuff in here
return new person($sql['firstName'], $sql['lastName']);
}
}
But now the heart of my question, is how do I implement a playerModel?
class playerModel{
public function getPlayer($playerId){
//would I do a join SQL here?
//or would I call personModel::getPerson()
//or do both these options couple the two classes too tightly?
}
}
Would some kind of factory class be another option? If so, how would that be done?
I need to be able to construct person, player, and coach objects, because I have users that will fall into all those categories.
Any feedback is greatly appreciated, and I’ll be checking back often if I need to clarify anything.
I will begin with your side question, since the terminology is the first important part when speaking about OOP:
person,playerandcoachare the Model. The intention of the Model is to project the important part of reality into a program, so that you (as a programmer) can intuitively work with the terms regarding the business domain.Your classes
personModelandplayerModelare less a model than a persistence controller or, as you said, a factory. If you would like to learn OOP and the possibilities to load/save a Model from/into a relational DB, you can easily write your own code, similar to your SQL code. A classDBManagementcould do the trick with operations likeloadPersons(). That operation queries the DB, builds all person objects and returns them. Similarly the saving can work withupdatePerson(person $person).Later you can use some kind of ORM (Object Relational Mapper) persistence framework (I don’t have experience with PHP myself, but doctrine ORM could be interesing. In Java or .Net often Hibernate is used).
Addionally I would suggest that you design your model in another way. Indeed you had the right idea to let
playerandcoachinherit fromperson, so that you can share common attributes like thefirstName. But in this case, that model is not flexible enough to allow what you mentioned in your last sentence, that some users fall in all categories. A special case is when a Person, which is actually a Player, will become a Coach. For example, if Martin is a player but shall become a coach now, you have to swap one Martin object for another. That means that Martin is not the same Person as before, just because he becomes a coach, and that sounds strange, doesn’t it?Instead you can define, that every user is always a
person. Some users arecoaches, some others areplayers, some are both and some are none. But always aperson.Some pseudo code for illustration:
This way every user (=Person) can have none to every role. If a user has a role then in that role object you can save specific role attributes for that user. Of course, a person’s role list can change over time, according to what role(s) the person actually has.
A neat sideeffect is that this model is more in line with your database schema, so that you should have no trouble to translate the relational DB schema into a model instance and vice versa.