Děkuji za odpověď, asi teď budu vypadat hloupě, ale nepochopil jsem to :-(, mohl bys mi to, prosím, zkusit vysvětlit jinak (více dopodrobna, možná maličký příklad - stačí v pseudokódu).
Já nad tím uvažoval tak, že abstraktní třídu bych tvořil, kdybych tam chtěl přidat i nějaké sloty / atributy - pak je logické, že to nemůže být interface. Původně jsem tak zvažoval jakýsi slot "id", který by obsahoval primární klíč tabulky, problém ale je, že ne každá tabulka má jako primární klíč jeden sloupec - není to časté, ale i takové se mi občas podaří udělat ;-). V tomto případě bych byl spíše pro ten interface, kde by byly, jak jsi říkal, metody "smazat dle primárního klíče", "uložit všechna data", ale jestli se nemýlím, tak v interface nemohu metody definovat, takže bych si nemohl "předprogramovat" žádný kousek kódu...
Teď mě tak napadá, to by se dalo automatizovat, ne? Kdybych si vytvořil abstraktní třídu, mohla by vypadat nějak takto (pseudokód):
abstract class DbTableRowObject
{
protected string tableName // název tabulky
protected array tableColumns // seznam sloupců tabulky
protected array primaryKeys // seznam sloupců tvořících primární klíč
__construct()
{
foreach (getDbColumns(tableName) as column => data) {
this->column = data->value // vytvoří atribut třídy
// potomek může mít i další atributy, takže je nutné uložit někam, které atributy se budou ukládat do databáze
this->tableColumns.push(column)
if (data->key == 'PRI') {
this->primaryKeys.push(column) // uloží sloupce tvořící primární klíč
}
}
}
public delete()
{
// projde primární klíče a vytvoří klauzuli WHERE
where = ''
foreach (this->primaryKeys as attribute) {
concat(where, ' AND ', key, ' = "', this->attribute, '"')
}
if (where == '') {
throw Exception('There is no primary key specified')
}
return Db::getHandler()->where(where)->delete(this->tableName)
}
// kontroluje povinné položky - většinou budou tato data přidávána a upravována přes HTML formulář
protected checkMandatories()
{
return true; // žádné povinné položky
}
public save()
{
this.checkMandatories()
// všechny hodnoty už musí být nastaveny, takže z nich vytvoříme pole s údaji do databáze
data = array()
foreach (this->tableColumns as attribute) {
data.push(attribute, this->attribute)
}
// jestliže jsou specifikovány (inicializovány) všechny sloupce primárního klíče, budeme updatovat, jinak insertovat
if (primaryKeySpecified()) {
// projde primární klíče a vytvoří klauzuli WHERE - stejné, jak u delete, ale to je teď jedno
where = ''
foreach (this->primaryKeys as column) {
concat(where, ' AND ', key, ' = "', this->column, '"')
}
return Db::getHandler()->where(where)->update(data)
} else {
return Db::getHandler()->insert(data)
}
}
}
Myslíš, že je to takto ok nebo to je nějak obecně špatné řešení? V tomto případě bych samozřejmě vůbec neřešil interface, ale použil bych tuto abstraktní třídu, ze které bych dědil, co říkáš/te?
Ještě jednou dík.