Attualmente sto sviluppando il mio primo layer personalizzato per la mappatura dei dati, ma ho riscontrato un problema concettuale che sembra essere nascosto su tutti i libri e le guide che ho letto.
Il mio problema è il seguente. Il mio data mapper conosce il database e mappa i campi del database (da più tabelle, non mostrate nell'esempio) ai campi del modello. Tuttavia, prima di creare il DataMapper, i miei campi modello erano ben incapsulati e avevano solo getter.
Ora, ho dovuto creare setter, anche se non li voglio, l'unica classe che dovrebbe mai impostare valori è il mapper (o il modello stesso). C'è un modo per aggirare questo?
In questo momento posso pensare a due modi, ma non mi piacciono molto neanche:
-
Inietti il mapper nel modello tramite un metodo factory statico e lascia che il modello associ i campi del programma di analisi dei dati ai propri campi. Ciò significherebbe che più o meno mapperò le cose due volte (dal database ai campi del mapper, quindi dai campi del compilatore ai campi del modello) e mi sembra molto sbagliato.
-
Usa __set al posto di setter specifici e usa reflection per identificare la classe chiamante, lasciando solo che il mapper corretto imposti effettivamente i valori. La mia lamentela è che preferirei non usare la riflessione in generale e che preferirei un'interfaccia ben definita per il modello.
Ecco i bit di codice rilevanti, nel caso in cui aiutano a capire il mio dilemma.
Controller:
$mapper = new Mapper();
$model = $mapper->find($id);
if ($model != null) {
// hook up view with model
}
Mapper:
public function find($id)
{
$pdoStatement = $this->database->select(static::getSelectStatement(), $id);
if ($pdoStatement != null) {
$values = $pdoStatement->fetch();
if (!empty($values) {
return $this->createObject($values);
}
}
}
private function createObject(array $values)
{
$model = new Model($values['id']); // needs ID, legacy constraint
// Now we come to the ugly part, setters I didn't need before
$model->setTitle($values['title']);
$model->setReleaseDate($values['date']);
// etc.
return $model;
}