Ich implementiere das Data Mapper-Designmuster in meiner Zend Framework-Webanwendung und alles läuft gut, ich genieße es wirklich, mit dem Datamapper in Zend zu arbeiten und nicht nur das Row Gateway-Muster anzuwenden, aber ich habe ein Problem bezüglich meiner Architektur. Ich bin mir nicht sicher, wie ich Verweis- und Arbeit mit Fremdschlüssel-Constraints im OOP-Stil mit meinem Datenmapper umsetzen soll. Also habe ich meine Model-Klasse, meine DbTable-Klasse und meine Mapper-Klasse. Sollte ich alle Fremdschlüsselbeziehungen in meine DbTable-Klasse setzen und auf diese Weise in meinem Mapper mit der findDependentRowset()
-Funktion abrufen können, oder wäre es besser, die abhängige Klasse in meinem Mapper zu instanziieren. Was ist die beste OOP-Praxis beim Zuordnen von Fremdschlüsseln unter Verwendung des Data Mapper-Musters?
Antworten
Zu viele Anzeigen?Ich würde mich für den DataMapper entscheiden, da die anderen beiden nicht unbedingt die ID kennen sollten, auch wenn sie für die Beziehungscaller immer notwendig ist.
Modell
- Eigenschaftszugriffsmethoden und private Eigenschaftsdatenhalter
- Funktionen zur korrekten Verwendung des Modells
- Beziehungscaller (ruft Beziehungsabfragen in der DbTable auf, um Eltern- oder Kindreihen zu erhalten) oder gibt zwischengespeicherte Daten zurück
DbTable
- Bietet alle statischen Funktionen zur Abfrage von Daten und zur Instanziierung der zugehörigen Modelle, z. B. getById, getByName, getByComplexSearch usw.
- Bietet alle statischen Beziehungsloader wie: getParents, getChildrens und alle anderen Versionen, die benötigt werden
DataMapper
- Übernimmt die eigentliche Arbeit und bietet die Methode getObjects, die entweder einen Abfrageabschnitt oder eine vollständige Abfrage akzeptiert und die Daten in die ModelObjects lädt und bei Bedarf in eine Update-, Insert- oder Löschabfrage zurückliest
- Der DataMapper sollte dafür verantwortlich sein, Beziehungsfehler beim Einfügen, Aktualisieren oder Löschen zu überprüfen und bei Verwendung von InnoDB Transaktionen zu verwenden.
Macht das irgendwie Sinn?
Früher hatte ich findDependentRowset
auf meinen Systemen. Aber nicht mehr! In den meisten Fällen ist es eine Verschwendung von Ressourcen. Tabellenverknüpfungen sollten in Ihrem SQL-Statement erfolgen.
Siehe meine Antwort hier: Hand made queries vs findDependentRowset
Ich bin noch weit davon entfernt, Doctrine oder Propel zu verwenden (ich habe es noch nie gebraucht). Vielleicht eines Tages. (Verwende jetzt Doctrine 2. Also... Ich schlage dir jetzt dasselbe vor)
ALTE ANTWORT
Nach ein paar Jahren Arbeit mit dem Zend Framework stieß ich auf die folgende Architektur:
1) Ich habe einen abstrakten Mapper, den alle meine Mapper erweitern: Zf_Model_DbTable_Mapper
2) Ich habe auch ein abstraktes Modell (Domain-Objekt), das dem Row Data Gateway ähnelt, mit der Ausnahme, dass es kein Gateway ist. Es ist ein generisches Domain-Objekt: Zf_Model
3) Wenn Objektgraphen (SQL-Joins) erstellt werden, delegiert ein Mapper an die anderen Mapper, die für das jeweilige Objekt verantwortlich sind.
Beispiel
Diese Methode stammt vom abstrakten Mapper:
public function getById($id)
{
$tableGateway = $this->getTable();
$row = $tableGateway->fetchRow('id =' . (int) $id);
if (!$row)
retur null;
$row = $row->toArray();
$objectName = $this->getDomainObjectName();
$object = new $objectName($row['id']);
$object->populate($row);
return $object;
}