Je me pose une petite question depuis quelques temps. Je me suis formé à JAVA ces derniers temps, et j'ai pu découvrir l'ORM Hibernate. Sans vouloir aller jusque là, et ne pouvant pas implémenter d'ORM sur ma base actuelle (PHP/Oracle), je cherche à m'adapter au mieux.
Je me pose alors des questions (existentielles ?) sur l'architecture que je dois mettre en oeuvre.
Actuellement, j'ai découpé mon application en plusieurs morceaux :
- Codeigniter pour la partie IHM MVC
- une couche Business qui est appelée par le contrôleur. Dans celle-ci, je mets en forme mes données avec en entrée les données brutes et en sortie un objet
- une couche DAO en CRUD qui est appelée par le business avec en paramètre de mes fonctions soit un objet, soit l'id unique de la ligne (dans le cas d'un read).
Visuellement ça ressemble à ça :
Mon model
<?php
class Model_direction extends MY_Model {
/* Attributs */
protected $id;
protected $libelle;
protected $division;
/* Constructeur */
public function __construct($id = '', $libelle = '') {
$this->setId($id);
$this->setLibelle($libelle);
parent::__construct();
}
/* Id */
public function getId() {
return $this->id;
}
public function setId($id) {
$this->id = $id;
}
/* Libellé */
public function getLibelle() {
return $this->libelle;
}
public function setLibelle($libelle) {
$this->libelle = $libelle;
}
/* Division */
public function getDivision() {
return $this->division;
}
public function setDivision(Model_division $division) {
$this->division = $division;
}
}
Mon Business
class Business_direction extends CI_Business {
/**
* Recherche des Model_direction suivant des paramètres
*
* @param String $id est l'identifiant de la direction
* @param String $libelle est le libellé de la direction
* @param String $id_division est l'identifiant de la division
* @return false si échec
* @return array(Model_direction) si réussite
*/
function rechercher($id = '', $libelle = '', $id_division = '') {
/* On crée l'objet de recherche */
$dr = new Model_direction($id, $libelle);
if (strlen($id_division) > 0) {
$dr->setDivision(new Model_division($id_division));
}
/* On lance la recherche */
$result = Dao_direction::search($dr);
return $result;
}
/**
* Récupération d'un Model_direction suivant son id
*
* @param String $id est l'identifiant de la direction
* @return false si échec
* @return Model_direction si réussite
*/
function lire($id) {
/* On crée l'objet de recherche */
$direction = new Model_direction($id);
/* On lance la recherche */
$result = Dao_direction::read($direction);
if (!($result instanceof Model_direction) {
return false;
}
return $result;
}
}
Mon DAO
class Dao_direction extends CI_Dao {
/**
* Recherche des Model_direction suivant un objet Model_direction
*
* @param Model_direction $direction
* @return Array d'objets Model_direction
*/
public function search(Model_direction $direction, $profondeur = 0) {
/* Construction de la requête */
$this->db->select('DR.ID, DR.ID_DIVISION, DR.LIBELLE');
$this->db->from('DIRECTION DR');
/* Filtre id */
if (strlen($direction->getId()) != 0) {
$this->db->like('DR.ID_DR', $direction->getId(), 'none');
}
/* Filtre libellé */
if (strlen($direction->getLibelle()) != 0) {
$this->db->like('DR.LIBELLE', $direction->getLibelle());
}
if ($direction->getDivision() instanceof Model_division) {
$division = $direction->getDivision();
/* Filtre division */
if (strlen($division->getId()) != 0) {
$this->db->where('DR.ID_DIVISION', $division->getId());
}
}
$this->db->order_by('DR.LIBELLE', 'asc');
/* On lance la requête */
$query = $this->db->get();
/* On crée la liste des directions */
$result = array();
foreach ($query->result_array() as $element) {
/* On crée l'objet Model_direction */
$direction = new Model_direction($element['ID'], $element['LIBELLE']);
if ($profondeur > 0) {
$direction ->setDivision(
Dao_division::read($element['ID_DIVISION'], $profondeur-1));
}
$result[] = $direction;
}
return $result;
}
public function read($id, $profondeur = 0) {
$direction = new Model_direction($id);
$result = self::search($direction, $profondeur);
if (count($result) == 1) {
return $result[0];
} else {
return false;
}
}
}
Ça fonctionne bien, mais ça a ses limites :- La relation 1-1 est parfaite, mais la relation 1-n est assez tordue pour moi. Je ne vois pas comment la mettre en place. Par exemple, si l'on se base non plus sur la direction mais sur la division, on peut donc avoir plusieurs direction par division. Le schématiser est assez complexe. Avez-vous une solution à cette problématique ? Des exemples ?
- La recherche profonde est très complexe à mettre en oeuvre. Si l'on se base sur la table direction et que l'on veut faire un filtre 3 tables au dessous, c'est actuellement impossible, à part de filtrer les retours en php : trop gourmand en mémoire, processeur et bande passante pour des données qui ne serviront pas.
En bref, j'aimerai pouvoir me promener facilement dans des objets sans avoir ces problématiques, et sans devoir dupliquer mon code ou faire à chaque fois des requêtes spécifiques. Avez-vous déjà rencontré un tel problème ? Comment l'avez-vous résolu ?
Merci