У меня есть классическая (исключительная) структура супертипа-подтипа (модель EERD). Мой DDL — это SQL (MySQL как RDBMS), поэтому мне нужно как-то преобразовать эту модель EERD в ERD.
Наконец я наклоняюсь Таблица наследования таблиц классов:
Когда приходит время написания кода для реализации всего этого, возникают некоторые сомнения.
Мое первое, хотя было сделать супертип полным незнанием подтипов так что я могу увеличивать / уменьшать количество подтипов, не касаясь класса супертипов.
Давайте сосредоточимся на U от CRUD: Обновить регистр в таблицах супертип-подтип.
Теперь у меня есть что-то вроде этого: контроллер + классы DAO / VO в PHP.
Примечание: код уменьшен для удобства чтения
Класс объекта доступа к данным супертипа:
//Supertype DAO class
class SupertypeDAO {
protected $db;
public function __construct($db) {
$this->db = $db;
}
//method that will be called by the subtype update method
protected function update($id, $changes){
$sql = "UPDATE supertype SET title = ".$this->db->quote($changes['title'])."WHERE id = ".$this->db->quote($id);
return $this->db->exec($sql); //true/false
}
}
Подтип_1 Класс доступа к данным:
//Subtype1 DAO class
class Subtype1DAO extends Supertype{
//method for updating ONLY the subtype table fields
protected function updateSubtypeProps($id, $subtype_changes){
//reduced code for readability purpose
$sql = "UPDATE subtype1 SET field1= ".$this->db->quote($subtype_changes['field1'])." WHERE id = ".$this->db->quote($id);
return $this->db->exec($sql); //true/false
}
//method that will be called by controller
public function update($id, $changes){
$this->db->beginTransaction();
try{
//update supertype
$res1 = parent::update($id, $changes);
if($res1 !== FALSE) throw new PDOException; //no false positives
//update subtype1
$res2 = $this->updateSubtypeProps($id, $subtype_changes);
if($res2 !== FALSE) throw new PDOException; //no false positives
$this->db->commit();
}catch (PDOException $e) {
$this->db->rollBack();
}
}
}
И класс Controller для операции обновления (например, запрос API put / post)
class APIController {
public static function update($id){
//request params as $data ...
//set $db link ...
//instance of subtype
$subtype = self::createSubtype($data['discriminator']);
//update
$id = $subtype->update($data['id'], $data);
//API response
}
private static function createSubtype($discriminator){
switch(discriminator){
case 'subtype1':
$obj = new Subtype1DAO($this->db);
break;
case 'subtype2':
$obj = new Subtype2DAO($this->$db);
break;
case 'subtype3':
$obj = new Subtype3DAO($this->$db);
break;
//etc
}
return $obj;
}
}
Что меня беспокоит, так это то, что у меня есть метод обновления в каждом подтипе, который всегда одинаков (вызывает родительское обновление + вызывает обновление подтипа).
Если мы повторим это для каждой операции CRUD и для каждого подтипа, слишком много повторений, не так ли?
Плохая практика?
Должен ли Супертип знать о подтипах?
Какова будет правильная реализация кода?
Задача ещё не решена.
Других решений пока нет …