Plusieurs methodes ou une seule "grosse" methode ?

Mammouth du PHP | 531 Messages

15 janv. 2009, 23:12

Bonjour,

Je me pose une question, étant confronté à ce problème.

J'étais en train de créer une méthode pour récupérer un listing depuis une base de donné que j'ai nommé getAll()

Seulement, obtenir un listing complet si il y a beaucoup d'entrées, ça risque de ramer dur... surtout si je récupère tout le contenu pour retourner une collection d'objets.

Je me disais donc, on va laisser la possibilité de paramétrer le LIMIT de la requête, ce qui permettra de gérer la pagination.

Mais cela m'amène maintenant à me dire que je pourrais avoir besoin de paramétrer la clause de la requête, par exemple n'avoir que les résultat pour une date donnée. Mais si je résonne comme ça je vais vite avoir un gros tas de paramètres dans ma méthode et le code va devenir complexe.

L'autre solution serait de faire autant de méthodes qu'il pourrais y avoir de possibilités, soit beaucoup de méthodes...

Exemple
- getAll()
- getLast(0, $limit)
- getWhereDate($date)
- getWhereMonth($month)
etc...

Voilà,
Je suis un peu pommé sur la méthode à employer... :?

ViPHP
ViPHP | 1136 Messages

16 janv. 2009, 09:00

Salut ,

Perso , au choix , je suis plus pour factoriser ta méthode ...

Pour des raisons évidentes de maintenance et de clarté !

Administrateur PHPfrance
Administrateur PHPfrance | 3131 Messages

16 janv. 2009, 11:32

Je ferais une méthode
getWhere(array $where, string $joins = null, string $groupby = null, int $limit = null)
où $where est un tableau associatif de la forme "nom du champ" => "valeur" ou "nom du champ" => array("valeur", "opérateur"), et ensuite à chaque fois que tu as un besoin qui peut s'exprimer (du type "getByDate", "getAll", etc...) tu crées la méthode correspondante, qui appelle celle-là.
Dans cette méthode tu t'occuperas de construire la where-clause à partir de ce tableau associatif, de faire les échappements nécessaire (valeurs séparés par des virgules dans le cas d'un array, échappements dans le cas d'une chaine, etc...) et d'exécuter la requête SELECT et de renvoyer la liste des résultats transformés.
Pour pouvoir gérer tout ce qui est cas particulier, tu pourras ajouter comme je l'ai fait des arguments supplémentaires à traiter "tel quel" :
function getWhere(array $where = array(), $joins = null, $groupby = null, $orderby = null, $limit = null)
{
  // 1. Construire la where-clause
  $where_clause = '...'; // c'est la partie la plus intéressante, je ne vais pas te priver de ce plaisir :)

  // 2. Constuire la requête (exemple de façon dont on pourrait générer cette requête)
  $sql = sprintf('SELECT %s FROM %s %s WHERE %s %s %s %s', 
    $fields, $table_name,
    !is_null($joins) ? 'JOIN '.$joins : '',
    $where_clause,
    !is_null($groupby) ? 'GROUP BY '.$groupby : '',
    !is_null($orderby) ? 'ORDER BY '.$orderby : '',
    !is_null($limit) ? 'LIMIT '.$limit);

  // 3. Exécuter la requête, extraire les résultats et transformer ça en array of Entree
  return array(...); // là ça dépend de ton environnement
}
/**
 * Renvoie la liste des entrées, sauf celles dont l'ID est indiqué
 * 
 * @param array $ids Excluded IDs (si vide, renvoie tout)
 * @return array
 */
function getAllBut(array $ids = array())
{
  return $this->getWhere(array(
    'id' => array($ids, 'NOT IN'),
  ));
}

/**
 * Renvoie les entrées
 * 
 * @param array $ids Ne renvoyer que les entrées ayant un de ces IDs (si vide, renvoie tout)
 * @return array
 */
function getAll(array $ids = array())
{
  return $this->getWhere(array(
    'id' => array($ids, 'IN'),
  ));
}

/**
 * Renvoie une entrée par son ID
 * 
 * @param int $id
 * @return Entree
 */
function getByID($id)
{
  $results $this->getAll(array($id));

  return @$results[0];
}

/**
 * Renvoyer les dernières entrées
 *
 * @param int $nb
 * @return array
 */
function getLast($nb = 1)
{
  return $this->getWhere(array(), null, null, 'date DESC', $nb);
}

Mammouth du PHP | 531 Messages

17 janv. 2009, 14:35

Merci pour vos réponse.

Je suis partagé entre vos 2 avis. Tout dispatcher en plusieurs méthodes ferrait beau coups trop de méthode et une seule grosse méthode comme l'exemple de naholyr, wouha c'est énorme, trop à mon goût. Merci pour cet exemple, c'est quand même très instructif.

Pour prendre un exemple j'ai pour l'instant une méthode de base :
public function getAll(){
		global $cnx;
		$req = "SELECT * FROM news";
		$res = $cnx->query($req);
		$liste = new collection();
		while($row = $res->fetch(PDO::FETCH_OBJ))
		{
			$user = gestionUser::getUniq($row->idUser);
			$news = new news($row->idNews, $row->titre, $row->date, $row->content, $row->etat, $user);
			$liste->add($news);
		}
		return $liste;
	}
Sachant que je peut avoir besoin de 4 cas particuliers :
- Obtenir toutes les news ( fonction actuelle )
- Obtenir toutes les news en ligne ( Where etat = 1 )
- Obtenir toutes les news brouillon ( Where etat = 0 )
- Obtenir les news de l'enregistrement x à y ( limit $x, $y )
+ en option :
- de tel auteur ( where auteur = toto )
- Classées par date ( order by date )
- Classées par titre ( ordre by titre )

Je pense que ça peut se faire en deux fonctions :
- getAll( $etat, $limit, $orderBy, $orderAsc )
- getAllToAuteur( $etat, $limit, $orderBy, $orderAsc )


Qu'en pensez-vous ? je trouve que c'est un compromis entre trop de méthode et une seule complexe... mais je suis pas spécialiste.