Zasadniczo masz trzy podejścia do tego problemu (jedno z nich natychmiast wyeliminuję):
- Jeden stół na klasę (to ten, który wyeliminuję);
- Typ rekordu z opcjonalnymi kolumnami; i
- Typ rekordu z tabelą podrzędną w zależności od typu, do którego się przyłączasz.
Dla uproszczenia generalnie polecam (2). Więc kiedy już masz swój stół:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
type VARCHAR(10),
name VARCHAR(100)
);
gdzie typ może być 'AGENT' lub 'LEAD' (na przykład). Alternatywnie możesz użyć kodów jednoznakowych. Następnie możesz zacząć wypełniać puste miejsca modelem obiektowym:
- Masz klasę nadrzędną użytkownika;
- Masz dwie klasy podrzędne:Lead i Agent;
- Te dzieci mają ustalony typ.
i powinien dość łatwo wskoczyć na swoje miejsce.
Co do tego jak załadować w jednym zestawieniu to bym użył jakiejś fabryki. Zakładając te klasy szkieletów:
class User {
private $name;
private $type;
protected __construct($query) {
$this->type = $query['type'];
$this->name = $query['name'];
}
...
}
class Agent {
private $agency;
public __construct($query) {
parent::constructor($query);
$this->agency = $query['agency'];
}
...
}
class Lead {
public __consruct($query) {
parent::constructor($query);
}
...
}
fabryka może wyglądać tak:
public function loadUserById($id) {
$id = mysql_real_escape_string($id); // just in case
$sql = "SELECT * FROM user WHERE id = $id";
$query = mysql_query($sql);
if (!query) {
die("Error executing $sql - " . mysql_error());
}
if ($query['type'] == 'AGENT') {
return new Agent($query);
} else if ($query['type'] == 'LEAD') {
return new Lead($query);
} else {
die("Unknown user type '$query[type]'");
}
}
Alternatywnie, możesz ustawić metodę fabryczną jako metodę statyczną na, powiedzmy, klasie User i/lub użyć tabeli przeglądowej dla typów do klas.
Być może zanieczyszczanie klas zasobem wyników zapytania w ten sposób jest wątpliwym projektem w najściślejszym sensie OO, ale jest to proste i działa.