Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

class connexion base de donnee

5 réponses
Avatar
jeancito
Bonjour à tous !

Je suis entrain de tenter de créer une classe en php5
afin de me mettre à la programmation objet

pourriez vous m'indiquer quelles sotn mes erreurs
et les améliorations à effectuer ?

Je vous remercie par avance pour vos suggestions

Jean Marc

<?
class connexion {

public $host;
public $user;
public $database;
public $password;

function _construct($host,$user,$password,$database)
{
$this->host=$host;
$this->user=$user;
$this->database=$database;
$this->password=$password;
}

function _destruct(){
}

function se_connecter($host,$user,$password)
{
mysql_connect($host,$user,$password);
}

function choisir_base($database){
$database='ocsweb';
mysql_select_db($database);
}

function executer_requete()
{
$sql="select*from ocsweb";
$requete=mysql_query($sql);
}

function afficher_resultat()
{
mysql_fetch_array($requete);
}
}

$nouvelle_connexion=new connexion('localhost','root','','ocsweb');
$nouvelle_connexion->se_connecter('localhost','root','');
$nouvelle_connexion->choisir_base('ocsweb');
$nouvelle_connexion->executer_requete($sql);
$nouvelle_connexion->afficher_resultat($requete);

?>

5 réponses

Avatar
bruno at modulix
jeancito wrote:
Bonjour à tous !

Je suis entrain de tenter de créer une classe en php5
afin de me mettre à la programmation objet
<troll pilosity="mild">

Si c'est pour apprendre la POO, choisis plutôt un langage objet (Python,
Ruby, Smalltalk, ...)
</troll>

pourriez vous m'indiquer quelles sotn mes erreurs
et les améliorations à effectuer ?

Je vous remercie par avance pour vos suggestions


<warning mode="je tape dur mais c'est pour ton bien">
Attend de lire mes commentaires avant de remercier... Je ne sais pas si
tu seras toujours d'humeur après !-)
</warning>



<?
class connexion {

public $host;
public $user;
public $database;
public $password;


Un puriste t'expliquera que ces attributs devraient être protégés.

Je ne suis pas pour ma part un ardent défenseur des modificateurs
d'accès (il n'y en a pas en Python, on se contente d'une convention de
nommage), mais en l'occurrence, ces attributs ne devraient pas pouvoir
être modifiés directement - une fois la connection établie au moins.

A ce propos, le handle de connection, tu le ranges où ?

function _construct($host,$user,$password,$database)
{
$this->host=$host;
$this->user=$user;
$this->database=$database;
$this->password=$password;
}

function _destruct(){


Ce serait le moment d'appeler mysql_close(), avec le handle de
connection retourné par mysql_connect()...
}

function se_connecter($host,$user,$password)
{
mysql_connect($host,$user,$password);


1/ A quoi ça te sert de passer host, user et pass alors que tu les a
déjà passé au constructeur (et ne les utilise pas) ?

2/ mysql_connect() renvoie un handle de connection, qui doit être
utilisé pour les opérations suivantes. Accessoirement, la connection
peut échouer, auquel cas mysql_connect retourne NULL. Il faut aussi
gérer ce cas.

3/ S'il y a déjà une connection en cours, tu en fais quoi ?

}

function choisir_base($database){
$database='ocsweb';
mysql_select_db($database);


1/ Ca sert à quoi de passer le nom de la base si tu l'écrase avec une
valeur codée en dur ? (ce qui, BTW, ne rend pas vraiment ta classe
réutilisable)

2/ ça sert à quoi de passer le nom de la base au constructeur si tu ne
t'en sert pas ? Et si tu change de base sans modifier la valeur de
l'attribut $database, ce dernier risque de donner des infos erronnées...

3/ mysql_select() attend un handle de connection (celui retourné par
mysql_connect()).

4/ Si mon souvenir est bon, mysql_select_db() retourne quelque chose...
par exemple, un code d'erreur.

5/ Qu'est-ce qui se passe si la connection n'a pas été ouverte avant ?

}

function executer_requete()
{
$sql="select*from ocsweb";
$requete=mysql_query($sql);


1/ la requete devrait être passée en argument

2/ mysql_query attend un handle de connection (celui retourné par
mysql_connect()).

3/ tu fais quoi du résultat de l'appel à mysql_query() ?

4/ Qu'est-ce qui se passe si la connection n'a pas été ouverte avant ?

}

function afficher_resultat()
{
mysql_fetch_array($requete);


1/ Elle vient d'où la variable $requete ?

2/ tu fais quoi de la valeur de retour de fetch_array()

3/ tu affiches quoi, là ?

4/ Qu'est-ce qui se passe s'il ny a pas eu de requete avant ?

}
}

$nouvelle_connexion=new connexion('localhost','root','','ocsweb');
$nouvelle_connexion->se_connecter('localhost','root','');
$nouvelle_connexion->choisir_base('ocsweb');


T'a pas un peu l'impression de te répéter, là ?-)

$nouvelle_connexion->executer_requete($sql);


Si tu n'a pas un warning, c'est qu'il est temps de corriger ton php.ini
et de mettre les alertes au niveau maxi (toujours les alertes au niveau
maxi en développement).

$nouvelle_connexion->afficher_resultat($requete);


Et c'est quoi le résultat ???

?>


Avant de vouloir faire de l'objet, il faudrait peut-être apprendre à
utiliser correctement l'API mysql...


En ce qui concerne l'aspect purement OO, maintenant... Tu a pas mal
d'opérations dont le fonctionnement dépend des opérations précédentes
(tu ne peux pas choisir une base sans être connecté, tu ne peux pas
passer une requete sans être connecté, tu ne peux pas afficher les
résultats d'une requête sans avoir effectuer la requête avant, etc).

En objet, on préfère essayer de faire en sorte que chaque message puisse
être envoyé sans se soucier des messages envoyés précédemment.

Actuellement, tu te contentes de reprendre l'API mysql telle que (et de
façon incorrecte, mais c'est un autre problème), ce qui ne sert pas à
grand chose. Ta classe devrait simplifier la vie du programmeur, en
gérant elle-même les détails. Par exemple, pour une requête select,
s'assurer qu'il y a une connection en cours (et se connecter sinon, et
gérer les erreurs éventuelles, sélectionner la base, etc), passer la
requête (et gérer les erreurs éventuelles), récupérer les résultats, et
libérer les ressources...

(Une autre approche est d'utiliser le pattern State pour gérer les
états, mais je pense que c'est franchement prématuré dans ton cas).

HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"

Avatar
FreakDev
bjr,

ce que je vais vous dire n'est pas forcément parole d'évangile, mais
bon c'est comme ça que je vois les choses...

en générale les données membres d'une classe sont privées et ont
fait un accesseur et un modificateur pour chaqu'une d'elles.


je ne voit pas l'utilité de paramétré la méthode se_connecter si
ces paramètre sont déja des données membre de la classe (d'autant
plus que les paramètre n'affecte même pas les données membres, c'est
à ce demander à koi elle serve ces données !!!).
[idem pour la methode choisir_base]


c'est surement une inatention de votre part, mais la methode affiche
résultat ne renvoie rien... pour une methode qui, d'après son nom,
affiche le résultat, c'est quand mêma pas pratique.

de plus ce script doit renvoyer une erreur quand on appelle la fonction
affiche_résultat, car la variable $resultat n'est pas initialisée
(dans le contexte de la méthode en question). effectivement $resultat
n'est ni une variable globale (ce qui ne serais pas judicieux) mais
n'est pas non plus une donnée membre (ce qu'il faudrait qu'elle soit).

encore une petite remarque, à la fin de votre script, vous appellez
afficher_resultat, et executer_requete avec un paramètre
(respectivement $requete et $sql) alors que ni l'une ni l'autre de ces
2 méthodes n'est paramétrée...



voila déja un certain nombre de modifications à faire ;)
Avatar
bruno at modulix
FreakDev wrote:
bjr,

(snip)


de plus ce script doit renvoyer une erreur quand on appelle la fonction
affiche_résultat, car la variable $resultat n'est pas initialisée


s/resultat/requete/

(dans le contexte de la méthode en question). effectivement $resultat
n'est ni une variable globale (ce qui ne serais pas judicieux) mais
n'est pas non plus une donnée membre (ce qu'il faudrait qu'elle soit).


Certainement pas.

Le problème ici vient de ce que l'exécution de la requête et la
récupération des résultats sont disjoints (à l'image de l'API mysql,
mais si c'est pour reproduire l'API mysql, je ne vois pas bien
l'intérêt), alors qu'une seule méthode devrait gérer les deux opérations:

// pseudocode (je n'ai pas vérifié les api exactes)

protected function _query($sql) {
assert ($this->_connection);
return mysql_query($sql, $this->_connection);
}

function select($sql) {
$q = $this->_query($sql);
if (is_resource($q)) {
return mysql_fetch_array($q);
}
else {
// gerer l'erreur
}
}


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"

Avatar
ftc
(dans le contexte de la méthode en question). effectivement $resultat
n'est ni une variable globale (ce qui ne serais pas judicieux) mais
n'est pas non plus une donnée membre (ce qu'il faudrait qu'elle soit).



Certainement pas.

Le problème ici vient de ce que l'exécution de la requête et la
récupération des résultats sont disjoints (à l'image de l'API mysql,
mais si c'est pour reproduire l'API mysql, je ne vois pas bien
l'intérêt), alors qu'une seule méthode devrait gérer les deux opérations:

// pseudocode (je n'ai pas vérifié les api exactes)

protected function _query($sql) {
assert ($this->_connection);
return mysql_query($sql, $this->_connection);
}

function select($sql) {
$q = $this->_query($sql);
if (is_resource($q)) {
return mysql_fetch_array($q);
}
else {
// gerer l'erreur
}
}



On peut pousser un peu plus loin, la méthode "select($sql)" devient
"selectOne($sql)" puisque manifestement elle ne retourne que le premier
résultat.

On pourrait créer une méthode "select($sql)"de la sorte:

function select( $sql ) {
$q = $this->_query( $sql );
if( is_resource( $q ) ) {
return new MySQLResultSetIterator( $q );
}
else {
//erreur
}
}

avec une définition de MySQLResultSetIterator qui implante l'interface
Iterator.

et puis ajouter les méthodes "insert" et "update" qui ont des
comportement différents de select.


Avatar
bruno at modulix
ftc wrote:

(snip)

On peut pousser un peu plus loin,


s/on peut/il faut/ !-)

(snip)

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"