2009-10-19 1 views
0

Notre solution actuelle ORM utilise les données cartographes pour représenter les tables/vues dans la base de données qui renvoient alors un objet de collection qui peut être utilisé pour parcourir les enregistrements récupérés comme des objets du modèle. Entre les couches Mapper et modèle de données est une couche de référentiel qui gère les requêtes de domaine aux cartographes de données et renvoie les collections correspondantes ou objets de domaine. Nous envisageons actuellement de restructurer les responsabilités des couches Repository et Data Mapper afin que toutes les demandes d'application à la couche Data Mapper soient acheminées à travers le Repository et que le Data Mapper renvoie les lignes de données récupérées au Repository qui retourne ensuite le collecte nécessaire à l'objet demandeur. Ce que je me demande, c'est si c'est une bonne pratique de passer l'ensemble de l'objet Repository dans le Data Mapper correspondant afin de pouvoir appliquer l'accès aux Data Mappers uniquement à travers la couche Repository.Comment appliquer correctement l'utilisation correcte d'une méthode de classe?

À titre d'exemple, c'est fondamentalement la façon dont il fonctionne maintenant:

class DataMapper { 

public function findAll(Criteria $criteria) 
{ 
    $select = $criteria->getSelect(); 

    // Build specific select statement 

    $rows = $this->_fetchAll($select); 

    return new Collection(array('data' => $rows, 'mapper' => get_class($this))); 
} 
} 

Je pense à faire quelque chose comme ceci:

class Repository { 

public function findAllByName(Model $model) 
{ 
    $this->_criteria->addCondition('name LIKE ?', $model->name); 

    $rows = $this->_mapper->findAll($this); 

    return new Collection(array('data' => $rows, 'repository' => get_class($this))); 
} 

} 

class DataMapper { 

public function findAll(Repository $repository) 
{ 
    $select = $repository->getCriteria()->getSelect(); 

    // Build specific select statement 

    $rows = $this->_fetchAll($select); 

    return $rows; 
} 
} 

Et puis dans cette version, l'objet Collection lancerait un appel au dépôt qui pourrait d'abord chercher à travers ses objets mises en cache et seulement émettre un appel à la base de données pour charger le dossier si elle est nécessaire.

Répondre

1

Chris a une suggestion valable.

Il dépend en partie du contexte du code, mais la dépendance injection du dépôt dans les instances de DataMapper que vous créez, à savoir:

$repo = new Repository(); 

$mapper = new DataMapper($repo); 

vous évitera d'avoir par la suite passer que $ repo autour de chaque fois que vous voulez pour utiliser findAll(). IE:

$mapper->findAll(); 
$mapper->findAllByName(); 

Je trouve lorsque les paramètres deviennent une partie omniprésente de chaque appel de fonction que je fais, il est logique d'envisager de les transformer en variables d'instance (surtout quand ils sont identiques à chaque fois).

Si votre référentiel varie entre contexte/instances alors l'injection est plus logique. Si vous constatez que vous créez toujours une instance de référentiel et que vous souhaitez la recycler, un singleton peut être approprié.

Ce qui est bien avec Dependency Injection, c'est de clarifier cette idée de dépendance (ironique!). Si vous voulez l'appliquer, vous pouvez faire quelque chose comme lancer une exception si l'objet $ repo est null, ou pas une instance Repository, dans votre méthode __construct().

1

je peut-être faire un peu différemment. J'ajouterais une méthode setRepository (Repository $ repos) ainsi qu'une méthode getRepository(). Ensuite, dans votre méthode findAll, appelez getRepository(). Si setRepository() n'a pas encore été appelé, getRepository peut renvoyer une instance de référentiel par défaut.

Je voudrais créer peut-être aussi une interface pour la classe du référentiel afin que les différentes implémentations de dépôt peuvent être utilisés dans la classe DataMapper.

Ainsi, la méthode get pourrait ressembler à quelque chose comme

public function getRepository() 
{ 
    if (!$this->_repository) { 
     $this->_repository = new Repository(); 
    } 

    return $this->_repository; 
} 

et la méthode de jeu pourrait ressembler à quelque chose comme

public function setRepository(RepositoryInterface $repos) 
{ 
    $this->_repository = $repos; 
}