Class PHP5 de gestion de requetes SQL simples

Class PHP5 de gestion de requetes SQL simples - PHP - Programmation

Marsh Posté le 28-04-2006 à 00:05:11    

voila j'ai fait cette petite class en PHP5 car je trouve que meme si c'est assez facile de gérer ses requetes SQL, c'est bien pratique car le code en est d'autant plus simplifié. Elle fait tout de meme 650 lignes :)
 
donc l'avantage ,c'est qu'au lieu de faire :

Code :
  1. $SQL = mysql_connect('localhost','root','') or die (mysql_error()) ;
  2. mysql_select_db('base_sql',$SQL) or die(mysql_error()) ;
  3. // Requete SQL
  4. $Query = 'SELECT champ_1,champ_2,champ_3 FROM ma_table WHERE champ_4 > 5 AND champ_5="valeur" ORDER BY champ_1 DESC LIMIT 10,20' ;
  5. $ExeSQL = mysql_query($Query) or die(mysql_error()) ;
  6. // Exploitation des résultat
  7. while ( $Data = mysql_fetch_array($ExeSQL) )
  8. {
  9. .............................. // Code
  10. }


vous ferez :

Code :
  1. $GetData = new MySQL_select ;
  2. $GetData->From('ma_table');
  3. $GetData->SetFilter('champ_4','>',5) ;
  4. $GetData->SetFilter('champ_5','=','valeur') ;
  5. $GetData->SQLOrder('champ_1','DESC') ;
  6. $GetData->SetStart(10) ;
  7. $GetData->SetLimit(20) ;
  8. // On veux récupérer un tableau de donnée
  9. $GetData->ReturnValue('rows') ;
  10. // Récupération des données
  11. $RecupData = $GetData->Make() ;


 
Le gain ne se situe pas sur la longueur du code qui ne change que tres peu, ca permet surtout un évolution nettement plus facile ;)
 
Les procédures sont sensiblements les memes pour les autres classes, le gain de se fait pas sur la compacité du code mais sur sa facilité a évoluer.

Code :
  1. <?php
  2. // Librairie MySQL optimisée PHP5
  3. class MySQL {
  4. // Déclaration des variables de parametres
  5. private $MySQLServer = '' ;
  6. private $MySQLLogin  = '' ;
  7. private $MySQLPasswd = '' ;
  8. // Base de donnée(s)
  9. private $MySQLBdd = '' ;
  10. // Options
  11. private $OptLog = false ;
  12. // Variables techniques
  13. static $MySQLHandle ;
  14. static $MySQLNbQueries ;
  15. static $MySQLResult = array() ;
  16. // Fin de déclaration des variables
  17. // Déclaration des constructeurs/destructeurs de class
  18. // Constructeur
  19. function __construct()
  20. {
  21.  // Connexion a la base
  22.  $this->OpenSQLAccess() ;
  23. }
  24. // Destructeur
  25. function __destruct()
  26. {
  27. }
  28. // Fin de déclaration des constructeurs/destructeurs de class
  29. // Déclaration des procédures privées
  30. // Connexion base de donnée
  31. private function OpenSQLAccess()
  32. {
  33.  // Instanciation de la connexion
  34.  $this->MySQLHandle = mysql_connect($this->MySQLServer,$this->MySQLLogin,$this->MySQLPasswd) ;
  35.  // Selection de la base de donnée
  36.  mysql_select_db($this->MySQLBdd,$this->MySQLHandle) ;
  37. }
  38. // Fermeture de connexion base de donnée
  39. private function CloseSQLAccess()
  40. {
  41.  // Fermeture de connexion SQL
  42.  mysql_close($this->MySQLHandle) ;
  43.  // Valeur de retour
  44.  return true ;
  45. }
  46. // Type de requetes
  47. private function QueryType($Query)
  48. {
  49.  if(ereg("^UPDATE",$Query))
  50.  $return = "UPD" ;
  51.  elseif(ereg("^INSERT",$Query))
  52.  $return = "INS" ;
  53.  elseif(ereg("^DELETE",$Query))
  54.  $return = "DEL" ;
  55.  else
  56.  $return = "SEL" ;
  57.  // Retour final
  58.  return $return ;
  59. }
  60. //Déclaration des procédures publiques
  61. // Execution des requetes
  62. public function Execute($SQLQuery,$Back)
  63. {
  64.  // $Return (rows|res|null)
  65.  if(!is_array($SQLQuery))
  66.  {
  67.   $SQL = $SQLQuery ;
  68.   $SQLQuery = array($SQL) ;
  69.   // Réexecution de la procédure
  70.   $this->Execute($SQLQuery,$Back) ;
  71.  }
  72.  else
  73.  {
  74.   // On execute en boucle
  75.   foreach($SQLQuery As $Query)
  76.   {
  77.    // Execution de la requete
  78.    $ExecuteQuery = mysql_query($Query,$this->MySQLHandle) ;
  79.    // Type de requete
  80.    $QueryType = $this->QueryType($Query);
  81.    // Switch de retour
  82.    // switch sur la fonction a renvoyer
  83.    switch($QueryType)
  84.    {
  85.     // Select
  86.     case 'SEL':
  87.      // Switch de back
  88.      switch(strtoupper($Back))
  89.      {
  90.       case 'RES': $return = mysql_num_rows($ExecuteQuery) ; break ;
  91.       case 'ROWS' : $return = mysql_fetch_array($ExecuteQuery) ; break ;
  92.       default : $return = mysql_num_rows($ExecuteQuery) ; break ;
  93.      }
  94.     break ;
  95.      // Update
  96.     case 'UPD':
  97.      $return = mysql_affected_rows($this->MySQLHandle) ;
  98.     break ;
  99.      // Delete
  100.     case 'DEL':
  101.      $return = mysql_affected_rows($this->MySQLHandle) ;
  102.     break ;
  103.      // Insert
  104.     case 'INS':
  105.      switch($Back)
  106.      {
  107.       case 'RES': $return = mysql_affected_rows($this->MySQLHandle) ; break ;
  108.       case 'ID' : $return = mysql_insert_id(MySQL::$MySQLHandle) ; break ;
  109.       default : $return = mysql_affected_rows($this->MySQLHandle) ; break ;
  110.      }
  111.     break ;
  112.     case 'NULL':
  113.      $return = true ;
  114.     break ;
  115.    }
  116.   }
  117.  }
  118.  // Incrémentation des requetes
  119.  MySQL::$MySQLNbQueries++ ;
  120.  // Sauvegarde des résultats de la requete
  121.  MySQL::$MySQLResult[] = $return ;
  122.  // Renvoi final
  123.  return $return ;
  124. }
  125. // Fonction de log
  126. public function LogEvent($Text)
  127. {
  128.  // Si option activée
  129.  if( $this->OptLog )
  130.  {
  131.   // Ouverture
  132.   $fichier=fopen('mysql.log','w');
  133.   // Ecriture
  134.   fwrite($fichier,"[".date("d-m-Y H:i:s" )."] ".$Text."\n" );
  135.   fclose($fichier);
  136.  }
  137. }
  138. }
  139. // Class annexes - Insert
  140. class MySQL_insert extends MySQL {
  141. // Déclaration des variables statiques
  142. static $AllInsertQueries = array() ;
  143. // Déclaration des variables privéres
  144. private $SQLTable ;
  145. private $FieldsToUse ;
  146. private $Options ;
  147. private $Return = 'NULL' ;
  148. // Déclaration des procédures privées
  149. // Fonction de création de la requete SQL
  150. private function BuildSQLQuery()
  151. {
  152.  // On commence par verifier qu'on a toutes les informations en notre possession
  153.  if( empty( $this->SQLTable) )
  154.  {
  155.   // Le nom de la table SQL est vide - on log
  156.   $this->LogEvent('Impossible de construire la requete SQL, le nom de la table a utiliser non précisé');
  157.   // Renvoi faux
  158.   $return = false ;
  159.  }
  160.  // Ou si la liste des champs a insérer est vide
  161.  elseif( sizeof( $this->FieldsToUse ) == 0 )
  162.  {
  163.   // On log
  164.   $this->LogEvent('Liste des champs a insérer vide');
  165.   // Renvoi faux
  166.   $return = false ;
  167.  }
  168.  // Sinon tout est OK
  169.  else
  170.  {
  171.   // Début de la requete :
  172.   $SQLQuery = 'INSERT INTO '.$this->SQLTable.' (' ;
  173.   // On colle la liste des champs
  174.   $SQLQuery .= implode(',',array_keys($this->FieldsToUse)) ;
  175.   // Fermeture du nom des champs
  176.   $SQLQuery .= ') VALUES ("' ;
  177.   // Liste des valeurs de champs
  178.   $SQLQuery .= implode( '","',$this->FieldsToUse ) ;
  179.   // Fin de la requete
  180.   $SQLQuery .= '" )' ;
  181.   // On renvoie la requete
  182.   $return = $SQLQuery ;
  183.  }
  184.  // Renvoi final
  185.  return $return ;
  186. }
  187. // Déclaration des procédures publiques
  188. // Selection de la table
  189. public function Into($TblName)
  190. {
  191.  if(!ereg("^([:alnum:]+)$",$TblName))
  192.  {
  193.   // Nom de table uniquement alphanumérique
  194.   $this->LogEvent('Table SQL non alphanumerique');
  195.   // Renvoi faux
  196.   $return = false ;
  197.  }
  198.  else
  199.  {
  200.   // On enregistre le nom de la table
  201.   $this->SQLTable = strtolower($TblName) ;
  202.   // Renvoi vrai
  203.   $return = true ;
  204.  }
  205.  // Renvoi final
  206.  return $return ;
  207. }
  208. // Ajouts des paramètres
  209. public function SetValue($FieldName,$Value)
  210. {
  211.  if(ereg("^([:alnum:]+)$",$FieldName))
  212.  {
  213.   // S'assure que ca ne soit pas vide
  214.   $this->FieldsToUse[] = array('Name' =>$FieldName,
  215.       'Value' =>str_replace('"','\"',$Value) );
  216.   // Renvoi vrai
  217.   $return = true ;
  218.  }
  219.  else
  220.  {
  221.   // Le nom du champ est vide, on log une erreur
  222.   $this->LogEvent('Parametre des champs a ajouter sont vides ou ne sont pas alphanumeriques');
  223.   // Renvoi final
  224.   $return = false ;
  225.  }
  226.  // Renvoi final
  227.  return $return ;
  228. } //
  229. // Application des options
  230. public function Option($Field,$ArrayOfFunctions)
  231. {
  232.  // On vérifie que le champ a été répertorié
  233.  if(!isset($this->FieldsToUse[$Field]))
  234.  {
  235.   // On logue mais on ne bloque pas la procédure
  236.   $this->LogEvent('Impossible d\'utiliser des fontions sur le champ '.$Field.' car celui ci n\'est pas répertorié');
  237.  }
  238.  else
  239.  {
  240.   // on applique la/les options
  241.   if( is_array($ArrayOfFunctions) )
  242.   {
  243.    // On fait une boucle
  244.    foreach($ArrayOfFunctions As $Function)
  245.    {
  246.     // Si la fonction existe
  247.     if(function_exists($Function))
  248.     {
  249.      // On applique la fonction
  250.      $this->FieldsToUse[$Field] = $Function($this->FieldsToUse[$Field]) ;
  251.     }
  252.     else
  253.     {
  254.      // On logue mais on bloque pas
  255.      $this->LogEvent('Fonction '.$Function.' non déclarée');
  256.     }
  257.    }
  258.   }
  259.  }
  260. }
  261. // Attribution de la valeur de retour
  262. public function ReturnValue($Choice)
  263. {
  264.  // rows|res|id|null
  265.  $AcceptedValues = array('ROWS','RES','ID','NULL') ;
  266.  // Si ce n'est pas dans les valeur acceptées, on log mais on ne bloque pas
  267.  if( in_array($Choice,$AcceptedValues))
  268.  {
  269.   $this->Return = strtoupper($Choice) ;
  270.   // Renvoi vrai
  271.   $return = true ;
  272.  }
  273.  else
  274.  {
  275.   // On log
  276.   $this->LogEvent('Valeur de retour non acceptée : '.$Choice.' dans la procérure ReturnValue()');
  277.   // renvoi faux
  278.   $return = false ;
  279.  }
  280.  // renvoi final
  281.  return $return ;
  282. }
  283. // Execution de la requete
  284. public function Make()
  285. {
  286.  // On commence par générer la requete
  287.  $SQLQuery = $this->BuildSQLQuery() ;
  288.  MySQL_insert::$AllInsertQueries[] = $SQLQuery ;
  289.  // On verifie que le résultat n'est pas 'false'
  290.  if( $SQLQuery == false )
  291.  {
  292.   // Une erreur s'est produite - elle est loguée de toute facon
  293.   $this->LogEvent('Arret de procédure Make(), class MySQL_insert');
  294.   // Renvoi faux
  295.   $return = false ;
  296.  }
  297.  else
  298.  {
  299.   // On execute la requete
  300.   $return = $this->Execute($SQLQuery,$this->Return) ;
  301.   // Prendra faux automatiquement en cas d'erreur
  302.  }
  303.  // renvoi final
  304.  return $return ;
  305. }
  306. }
  307. // Class annexes - Select
  308. class MySQL_select extends MySQL {
  309. // Declaration des variables statiques
  310. static $AllSelectQueries ;
  311. // Declaration des variables privées
  312. private $SQLTable ;
  313. private $SQLFilters ;
  314. private $SQLExtractionFields ;
  315. private $SQLOrder = array ('field'=>'' , 'sens'=>'' );
  316. private $SQLLimit = array('start'=> false , 'lenght' => false ) ;
  317. private $Return = 'ROWS' ;
  318. // Déclaration des procédures privées
  319. private function BuildSQLQuery()
  320. {
  321.  // Debut de la requete
  322.  $SQLQuery = 'SELECT ' ;
  323.  // Liste des champs a extraire
  324.  $SQLQuery .= implode(',',$this->SQLExtractionFields) ;
  325.  // Nom de la table
  326.  $SQLQuery .= ' FROM '.$this->SQLTable ;
  327.  // Ajout des clauses de conditions si nécessaire
  328.  if( sizeof( $this->SQLExtractionFields ) > 0 )
  329.  {
  330.   $EachFilter = array() ;
  331.   // Continuation de la mise en forme de la requete
  332.   $SQLQuery .= ' WHERE ' ;
  333.   // On met en forme les filtres
  334.   foreach( $this->SQLFilters As $Filter )
  335.   {
  336.    if(!ereg("^[0-9]$",$Filter['value']))
  337.    {
  338.     $Filter['value'] = '"'.$Filter['value'].'"' ;
  339.    }
  340.    // On ajoute le filtre
  341.    $EachFilter[] = $Filter['field'].$Filter['op'].$Filter['value'] ;
  342.   }
  343.   // On colle les filtres avec du implode
  344.   $SQLQuery .= implode(' AND ',$EachFilter) ;
  345.   // On rajoute une clause eventuelle d'ordre
  346.   if( strlen($this->SQLOrder['field']) > 0 )
  347.   {
  348.    // On rajoute la clause
  349.    $SQLQuery .= ' ORDER BY '.$this->SQLOrder['field'] ;
  350.    // Si le sens est précisé on le rajoute
  351.    if( strlen($this->SQLOrder['sens']) > 0 )
  352.    {
  353.     $SQLQuery .= ' '.$this->SQLOrder['sens'] ;
  354.    }
  355.   }
  356.   // On vérifie l'attribut LIMIT
  357.   if($this->SQLLimit['lenght']!=false && $this->SQLLimit['start']!=false)
  358.   {
  359.    // LIMIT complet
  360.    $SQLQuery .= ' LIMIT '.$this->SQLLimit['start'].','.$this->SQLLimit['lenght'] ;
  361.   }
  362.   elseif($this->SQLLimit['lenght']!=false && $this->SQLLimit['start']==false )
  363.   {
  364.    // LIMIT semi-complet
  365.    $SQLQuery .= ' LIMIT '.$this->SQLLimit['lenght'] ;
  366.   }
  367.   // Requete SQL Complete
  368.   $return = $SQLQuery ;
  369.  }
  370.  else
  371.  {
  372.   // Aucun champ a extraire
  373.   $this->LogEvent('Aucun champ a extraire dans MySQL_select');
  374.   // Renvoi faux
  375.   $return = false ;
  376.  }
  377.  // Renvoi final
  378.  return $return ;
  379. }
  380. // Fin de déclaration des procédures privées
  381. // Déclaration des procédures publiques
  382. // Selection de la table SQL
  383. public function From($TblName)
  384. {
  385.  if(!ereg("^([:alnum:]+)$",$TblName))
  386.  {
  387.   // Nom de table uniquement alphanumérique
  388.   $this->LogEvent('Table SQL non alphanumerique');
  389.   // Renvoi faux
  390.   $return = false ;
  391.  }
  392.  else
  393.  {
  394.   // On enregistre le nom de la table
  395.   $this->SQLTable = strtolower($TblName) ;
  396.   // Renvoi vrai
  397.   $return = true ;
  398.  }
  399.  // Renvoi final
  400.  return $return ;
  401. }
  402. // Mise en place des filtres
  403. public function SetFilter($Field,$Op,$Value)
  404. {
  405.  // Operateurs acceptés
  406.  $AcceptedOperators = array('>','<','<=','>=','==','!=') ;
  407.  // Si $Value est un chiffre on ne met pas de guillemets
  408.  if(!ereg("^[0-9]$",$Value)){ $PutFilterValue = '"'.$Value.'"' ; }else{ $PutFilterValue = $Value ; }
  409.  // Si l'opérateur n'est pas reconnu
  410.  if( in_array($Op,$AcceptedOperators))
  411.  {
  412.   // On log
  413.   $this->SQLFilters[] = array('field'=>$Field,'op'=>$Op,'value'=>$PutFilterValue) ;
  414.  }
  415.  else
  416.  {
  417.   // On log
  418.   $this->LogEvent('Operateur logique non reconnu');
  419.   // Renvoi faux
  420.   $return = false ;
  421.  }
  422.  // renvoi final
  423.  return $return ;
  424. }
  425. // Longueur de l'extraction
  426. public function SetLimit($Int)
  427. {
  428.  if(!ereg("^[0-9]$",$Int))
  429.  {
  430.   // ce n'est pas un chiffre
  431.   $this->LogEvent('La limit doit etre de type Integer');
  432.   // renvoi faux
  433.   $return = false ;
  434.  }
  435.  else
  436.  {
  437.   $this->SQLLimit['lenght'] = $Int ;
  438.   // Renvoi vrai
  439.   $return = true ;
  440.  }
  441.  // renvoi final
  442.  return $return ;
  443. }
  444. // Debut de l'xtraction
  445. public function SetStart($Int)
  446. {
  447.  if(!ereg("^[0-9]$",$Int))
  448.  {
  449.   // ce n'est pas un chiffre
  450.   $this->LogEvent('La limit de début doit etre de type Integer');
  451.   // renvoi faux
  452.   $return = false ;
  453.  }
  454.  else
  455.  {
  456.   $this->SQLLimit['start'] = $Int ;
  457.   // Renvoi vrai
  458.   $return = true ;
  459.  }
  460.  // renvoi final
  461.  return $return ;
  462. }
  463. // Attribution de la valeur de retour
  464. public function ReturnValue($Choice)
  465. {
  466.  // rows|res|id|null
  467.  $AcceptedValues = array('ROWS','RES','ID','NULL') ;
  468.  // Si ce n'est pas dans les valeur acceptées, on log mais on ne bloque pas
  469.  if( in_array($Choice,$AcceptedValues))
  470.  {
  471.   $this->Return = strtoupper($Choice) ;
  472.   // Renvoi vrai
  473.   $return = true ;
  474.  }
  475.  else
  476.  {
  477.   // On log
  478.   $this->LogEvent('Valeur de retour non acceptée : '.$Choice.' dans la procérure ReturnValue()');
  479.   // renvoi faux
  480.   $return = false ;
  481.  }
  482.  // renvoi final
  483.  return $return ;
  484. }
  485. // Execution de la requete
  486. public function Make()
  487. {
  488.  // On commence par générer la requete
  489.  $SQLQuery = $this->BuildSQLQuery() ;
  490.  MySQL_select::$AllSelectQueries[] = $SQLQuery ;
  491.  // On verifie que le résultat n'est pas 'false'
  492.  if( $SQLQuery == false )
  493.  {
  494.   // Une erreur s'est produite - elle est loguée de toute facon
  495.   $this->LogEvent('Arret de procédure Make(), class MySQL_insert');
  496.   // Renvoi faux
  497.   $return = false ;
  498.  }
  499.  else
  500.  {
  501.   // On execute la requete
  502.   $return = $this->Execute($SQLQuery,$this->Return) ;
  503.   // Prendra faux automatiquement en cas d'erreur
  504.  }
  505.  // renvoi final
  506.  return $return ;
  507. }
  508. // Fin de déclaration des procédures publiques
  509. }
  510. // Class annexes - Update
  511. class MySQL_update extends MySQL  {
  512. // Déclaration des variables statiques
  513. static $AllUpdatesQueries ;
  514. // Déclaration des variables privées
  515. private $SQLtable ;
  516. private $SQLFilters = array() ;
  517. private $SQLLimit = false ;
  518. private $SQLUpdateFields = array();
  519. private $Return = 'NULL';
  520. // Déclaration des procédures privées
  521. private function BuildSQLQuery()
  522. {
  523.  // Début de la requete
  524.  $EachFieldToUpdate = array() ;
  525.  $EachFilterToSet = array() ;
  526.  // Vérification de la présence de toutes les informations
  527.  if(!empty($this->SQLtable))
  528.  {
  529.   // On vérifie qu'un champ au moins est a mettre a jour
  530.   if( sizeof($this->SQLUpdateFields) > 0 )
  531.   {
  532.    $SQLQuery = 'UPDATE '.$this->SQLtable.' SET ' ;
  533.    // On créé un tableau pour coller tous les éléments de la requete
  534.    foreach( $this->SQLUpdateFields As $Update )
  535.    {
  536.     $EachFieldToUpdate[] = $Update['field'].'="'.$Update['value'].'"' ;
  537.    }
  538.    // On colle les champs a mettre a jours
  539.    $SQLQuery .= implode(', ',$EachFieldToUpdate) ;
  540.    // On regarde ou non la présence d'une clause WHERE
  541.    if( sizeof($this->SQLFilters) > 0 )
  542.    {
  543.     // On ajoute la clause WHERE dans la raquete SQL
  544.     $SQLQuery .= ' WHERE ' ;
  545.     // Boucle pour créer les éléments de la boucle
  546.     foreach( $this->SQLFilters As $Filter )
  547.     {
  548.      $EachFilterToSet[] = $Filter['field'].$Filter['op'].$Filter['value'] ;
  549.     }
  550.     // On colle les conditions
  551.     $SQLQuery .= implode(' AND ',$EachFilterToSet) ;
  552.    }
  553.    // Ajout des attributs de LIMIT
  554.    if( $this->SQLLimit != false )
  555.    {
  556.     $SQLQuery .= ' LIMIT '.$this->SQLLimit ;
  557.    }
  558.    // Renvoi final
  559.    $return = $SQLQuery ;
  560.   }
  561.   else
  562.   {
  563.    // Aucun champ a mettre a jour
  564.    $this->LogEvent('Aucun champ a mettre à jour');
  565.    // Renvoi faux
  566.    $return = false ;
  567.   }
  568.  }
  569.  else
  570.  {
  571.   // Nom de table non renseigné
  572.   $this->LogEvent('Nom de table non renseigné');
  573.   // Renvoi faux
  574.   $return = false ;
  575.  }
  576.  // Renvoi global
  577.  return $return ;
  578. }
  579. // Mise en place des filtres
  580. public function SetFilter($Field,$Op,$Value)
  581. {
  582.  // Operateurs acceptés
  583.  $AcceptedOperators = array('>','<','<=','>=','==','!=') ;
  584.  // Si $Value est un chiffre on ne met pas de guillemets
  585.  if(!ereg("^[0-9]$",$Value)){ $PutFilterValue = '"'.$Value.'"' ; }else{ $PutFilterValue = $Value ; }
  586.  // Si l'opérateur n'est pas reconnu
  587.  if( in_array($Op,$AcceptedOperators))
  588.  {
  589.   // On log
  590.   $this->SQLFilters[] = array('field'=>$Field,'op'=>$Op,'value'=>$PutFilterValue) ;
  591.  }
  592.  else
  593.  {
  594.   // On log
  595.   $this->LogEvent('Operateur logique non reconnu');
  596.   // Renvoi faux
  597.   $return = false ;
  598.  }
  599.  // renvoi final
  600.  return $return ;
  601. }
  602. // Mise en place de la limit
  603. public function SetLimit($Int)
  604. {
  605.  // Uniquement un chiffre
  606.  if(ereg("^[:alnum:]$",$Int))
  607.  {
  608.   // On enregistre la limite
  609.   $this->SQLLimit = $Int ;
  610.   // renvoi vrai
  611.   $return = true ;
  612.  }
  613.  else
  614.  {
  615.   // N'est pas un chiffre
  616.   $this->LogEvent('La limite n\'est pas de type numérique, action ignorée');
  617.   // Renvoi faux ;
  618.   $return = false ;
  619.  }
  620.  // renvoi final
  621.  return $return ;
  622. }
  623. // Execution de la requete
  624. public function Make()
  625. {
  626.  // On commence par générer la requete
  627.  $SQLQuery = $this->BuildSQLQuery() ;
  628.  MySQL_update::$AllUpdatesQueries[] = $SQLQuery ;
  629.  // On verifie que le résultat n'est pas 'false'
  630.  if( $SQLQuery == false )
  631.  {
  632.   // Une erreur s'est produite - elle est loguée de toute facon
  633.   $this->LogEvent('Arret de procédure Make(), class MySQL_update');
  634.   // Renvoi faux
  635.   $return = false ;
  636.  }
  637.  else
  638.  {
  639.   // On execute la requete
  640.   $return = $this->Execute($SQLQuery,$this->Return) ;
  641.   // Prendra faux automatiquement en cas d'erreur
  642.  }
  643.  // renvoi final
  644.  return $return ;
  645. }
  646. }
  647. ?>


En espérant que ca vous aidera autant que ca m'aide, j'integrerai sous peu les jointures dans la class SELECT ;)
 
En passant j'aimerais avoir des suggestions d'optimisation ou des idées, bref des avis...

Message cité 1 fois
Message édité par the_bigboo le 28-04-2006 à 00:49:19
Reply

Marsh Posté le 28-04-2006 à 00:05:11   

Reply

Marsh Posté le 28-04-2006 à 00:21:50    

J'ai une suggestion.
 
Tu nous présente un cas d'utilisation pour appater le client, car un pavé comme ca ca me donne pas envie de le lire pour savoir comment l'utiliser. Pis les commentaires c'est bien, tant que ca fait pas "mis la juste pour le principe de mettre une ligne de commentaire par ligne de code"...

Reply

Marsh Posté le 28-04-2006 à 00:35:14    

Uhm, ton objet Mysql_select, il ne peut faire un select que sur une table ? Mes jointures, je les fais comment ?
 
Ta fonction  QueryType($Query), je la pige pas, tu fais un objet mysql_select pour les selects, un objet mysql_update pour des updates (je trouve ça bizare, mais bon...), donc tu connais le type de requête via l'objet, et tu refais une fonction pour connaitre le type de requête que tu fais dès fois que tu es pas sur  [:petrus dei]
 
 
 [:jean-guitou] et en pratique, tout ça, ça marche facilement ?

Message cité 1 fois
Message édité par zapan666 le 28-04-2006 à 00:36:08

---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 28-04-2006 à 00:42:40    

Mackila a écrit :

J'ai une suggestion.
Tu nous présente un cas d'utilisation pour appater le client, car un pavé comme ca ca me donne pas envie de le lire pour savoir comment l'utiliser. Pis les commentaires c'est bien, tant que ca fait pas "mis la juste pour le principe de mettre une ligne de commentaire par ligne de code"...


C'est vrai que je devrais mettre un exemple, quant aux commentaires moi je preferes les mettre en littéral plutot qu'en technique comme on le ferait en Java ou en C#, je trouve ca plus clair. Et un commentaire par ligne permet de bien expliquer le fonctionnement voila tout ;)
 
J'ai edité ;)

Reply

Marsh Posté le 28-04-2006 à 00:45:33    

the_bigboo a écrit :

C'est vrai que je devrais mettre un exemple, quant aux commentaires moi je preferes les mettre en littéral plutot qu'en technique comme on le ferait en Java ou en C#, je trouve ca plus clair. Et un commentaire par ligne permet de bien expliquer le fonctionnement voila tout ;)
 
J'ai edité ;)


ouais mais bon, des commentaires comme ça

Code :
  1. // Renvoi faux
  2. $return = false ;


On peut s'en passer  je pense [:ddr555]

Message cité 1 fois
Message édité par zapan666 le 28-04-2006 à 00:49:35

---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 28-04-2006 à 00:46:37    

zapan666 a écrit :

Uhm, ton objet Mysql_select, il ne peut faire un select que sur une table ? Mes jointures, je les fais comment ?
 
Ta fonction  QueryType($Query), je la pige pas, tu fais un objet mysql_select pour les selects, un objet mysql_update pour des updates (je trouve ça bizare, mais bon...), donc tu connais le type de requête via l'objet, et tu refais une fonction pour connaitre le type de requête que tu fais dès fois que tu es pas sur  [:petrus dei]
 [:jean-guitou] et en pratique, tout ça, ça marche facilement ?


Les jointures, je n'en utilises pas vraiment , la plupart du temps je n'en ai pas besoin mais je pense effectivement implémenter les jointures sous peu, comme dit, c'est a l'heure actuelle concu pour des requetes simple ;)
 
Comcernant la procédure queryType elle concerne les valeur de retour des procédures makes des objets
Par exemple sir tu veux avoir un nombre de résultat en retour, pour un SELECt tu utiliseras mysql_num_rows(), mais pour un UPDATE, ca sera mysql_affected_rows() Ca sert pour le switch ;)

Reply

Marsh Posté le 28-04-2006 à 00:47:36    

zapan666 a écrit :

ouais mais bon, des commentaires comme ça

Code :
  1. // Renvoi faux
  2. $return = false ;


On peut s'en basser  je pense [:ddr555]


oui, mais c'est une habitude, on a tous ses tics :D Et je me fais pas d'idée , si ca vous gene, il suffit de tater de la touche suppr :whistle:


Message édité par the_bigboo le 28-04-2006 à 00:47:59
Reply

Marsh Posté le 28-04-2006 à 00:49:11    

the_bigboo a écrit :

Les jointures, je n'en utilises pas vraiment , la plupart du temps je n'en ai pas besoin mais je pense effectivement implémenter les jointures sous peu, comme dit, c'est a l'heure actuelle concu pour des requetes simple ;)
 
Comcernant la procédure queryType elle concerne les valeur de retour des procédures makes des objets
Par exemple sir tu veux avoir un nombre de résultat en retour, pour un SELECt tu utiliseras mysql_num_rows(), mais pour un UPDATE, ca sera mysql_affected_rows() Ca sert pour le switch ;)


 
et pourquoi dans Mysql, tu ne mets pas la fonction Execute en abstrait, et tu la défini dans chaqun de tes objets ?  
 
Et quand on mets un switch, dans du code objet, la plupart du temps, c'est pas normal.


---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 28-04-2006 à 00:50:56    

zapan666 a écrit :

et pourquoi dans Mysql, tu ne mets pas la fonction Execute en abstrait, et tu la défini dans chaqun de tes objets ?  
 
Et quand on mets un switch, dans du code objet, la plupart du temps, c'est pas normal.


parce que ce qui me gene c'est que j'utilise $this dans chacun des objets et que je ne connais pas le comporteme,t que ca aurait si je la mettai en abstrait, si tu préfere je sais pas si elle va utiliser la classe parente ou le classe enfant , c'est p'tetre con mais bon...
 
Si tu me renseigne, je serai ravi de coriger :jap:
 
En quoi n'est-ce pas normal d'utiliser un switch dans du code objet :??:

Message cité 1 fois
Message édité par the_bigboo le 28-04-2006 à 00:51:56
Reply

Marsh Posté le 28-04-2006 à 01:02:39    

the_bigboo a écrit :

parce que ce qui me gene c'est que j'utilise $this dans chacun des objets et que je ne connais pas le comporteme,t que ca aurait si je la mettai en abstrait, si tu préfere je sais pas si elle va utiliser la classe parente ou le classe enfant , c'est p'tetre con mais bon...


Code :
  1. // Appel au parent
  2. parent::mafonction();
  3. parent::$mavariable;
  4. // Appel à l'objet (ça peut appeler une fonction du parents si la fonction n'est pas surchargé)
  5. $this->mafonction();
  6. $this->mavariable;


 

the_bigboo a écrit :


En quoi n'est-ce pas normal d'utiliser un switch dans du code objet :??:


 [:dao] Parce que
 
Bon, j'ai pas trouvé de la doc intéressante, mais normalement, tu peux t'en passer, genre sur ton code.
http://www.parashift.com/c++-faq-l [...] n-cpp.html


---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 28-04-2006 à 01:02:39   

Reply

Marsh Posté le 28-04-2006 à 03:58:28    

euh, on peut grave pas utiliser les fonctionnalités d'une bdd avec ton truc là.
Et tu te prends bien la tête, par exemple il suffit d'une fonction balançant les requetes à la base, pas la peine de faire dix milles fonctions et conditions en fonction des requetes.
 
Et donc là, comment je me connecte à plusieurs bdd, ou avec plusieurs comptes, comment je fais mes jointures, mes transactions, mes appels de procédure stockée ?
T'as voulu te faire un truc trop défini, donc pas du  tout évolutif, et limité forcément à tes connaissances SQL puisque tu essayes de prévoir chaque cas.
 
Critiquer c'est facile, donc demain au taf je mettrai la mienne, histoire de me faire poutrer (enfin je la pense bien plus fonctionnelle que la tienne malgré tout :p)

Message cité 1 fois
Message édité par Djebel1 le 28-04-2006 à 04:02:56
Reply

Marsh Posté le 28-04-2006 à 08:38:54    

Djebel1 a écrit :

euh, on peut grave pas utiliser les fonctionnalités d'une bdd avec ton truc là.
Et tu te prends bien la tête, par exemple il suffit d'une fonction balançant les requetes à la base, pas la peine de faire dix milles fonctions et conditions en fonction des requetes.
 
Et donc là, comment je me connecte à plusieurs bdd, ou avec plusieurs comptes, comment je fais mes jointures, mes transactions, mes appels de procédure stockée ?
T'as voulu te faire un truc trop défini, donc pas du  tout évolutif, et limité forcément à tes connaissances SQL puisque tu essayes de prévoir chaque cas.
 
Critiquer c'est facile, donc demain au taf je mettrai la mienne, histoire de me faire poutrer (enfin je la pense bien plus fonctionnelle que la tienne malgré tout :p)


Il n'est pas question de se faire poutrer ou quoi :p Mais de partager des points de vue ;)
personnelemment je l'ai faite en fonction de mes besoins , je me débrouille toujours pour ne pas avoir besoin de jointure meme si dans certains ca ce serait en effet assez pratique  :ange:  
D'autre part, les procédures stockées ne m'intéressent pas pour le moment car les applications qui s'executent au niveau PHP n'ont a l'heure actuelle aucun besoin d'etre déporté sur la base.
 
Effectivement ce serait cool que tu me montre comment tu as fait tes jointures :)
 

Reply

Marsh Posté le 28-04-2006 à 09:28:58    

the_bigboo a écrit :

Il n'est pas question de se faire poutrer ou quoi :p Mais de partager des points de vue ;)
personnelemment je l'ai faite en fonction de mes besoins , je me débrouille toujours pour ne pas avoir besoin de jointure meme si dans certains ca ce serait en effet assez pratique  :ange:  
D'autre part, les procédures stockées ne m'intéressent pas pour le moment car les applications qui s'executent au niveau PHP n'ont a l'heure actuelle aucun besoin d'etre déporté sur la base.
 
Effectivement ce serait cool que tu me montre comment tu as fait tes jointures :)


Le truc que je trouve dommange c'est que des librairies d'accès à des bases de données pour le coup il en existe déjà plein en php alors pourquoi en refaire une [:spamafote]
 
Prenons par exemple adodb(il en existe plein d'autres mais c'est celle que j'ai l'habitude d'utiliser), elle permet de faire tout ton bouzin sauf qu'en plus (entre autre):

  • c'est une vrai librairie d'abstraction (donc deux lignes à changer dans le config pour passer d'une base db2 à oracle ou même mysql)
  • elle gère la mise en cache des résultats
  • elle permet le bind de variables, les transactions, ou la génération automatique de requêtes insert/updates
  • plein d'autres trucs


Alors autant on peut critiquer les templates(cf vieille conversation), autant là j'aurais du mal à comprendre les avantages de le "refaire" à la main.

Reply

Marsh Posté le 28-04-2006 à 09:45:29    

anapajari a écrit :

Le truc que je trouve dommange c'est que des librairies d'accès à des bases de données pour le coup il en existe déjà plein en php alors pourquoi en refaire une [:spamafote]


Parce que bien que performantes elles sont souvent assez lourdes d'execution et leur utilisation toujours pas tres bien expliquée, j'ai survollé adodb comme tu l'indiquait, mais ya aucune doc d'utilisation ou je suis aveugle :??:

Reply

Marsh Posté le 28-04-2006 à 09:56:58    

the_bigboo a écrit :

Parce que bien que performantes elles sont souvent assez lourdes d'execution


Pourrais-tu expliquer ton propos? Je comprends pas ou tu veux en venir la :o
Tiens juste à titre d'exemple, deux benchmarks adodb ( le deuxième date un peu mais bon)
http://adodblite.sourceforge.net/benchmark.php
http://phplens.com/lens/adodb/
 

the_bigboo a écrit :

et leur utilisation toujours pas tres bien expliquée, j'ai survollé adodb comme tu l'indiquait, mais ya aucune doc d'utilisation ou je suis aveugle :??:


T'es aveugle ;) sur le lien donné, deuxieme ligne, "Documentation" et tu tombes sur

Reply

Marsh Posté le 28-04-2006 à 11:42:33    

anapajari a écrit :

Le truc que je trouve dommange c'est que des librairies d'accès à des bases de données pour le coup il en existe déjà plein en php alors pourquoi en refaire une [:spamafote]
 
Prenons par exemple adodb(il en existe plein d'autres mais c'est celle que j'ai l'habitude d'utiliser), elle permet de faire tout ton bouzin sauf qu'en plus (entre autre):

  • c'est une vrai librairie d'abstraction (donc deux lignes à changer dans le config pour passer d'une base db2 à oracle ou même mysql)
  • elle gère la mise en cache des résultats
  • elle permet le bind de variables, les transactions, ou la génération automatique de requêtes insert/updates
  • plein d'autres trucs


Alors autant on peut critiquer les templates(cf vieille conversation), autant là j'aurais du mal à comprendre les avantages de le "refaire" à la main.


complètement d'accord avec toi, mais au moment où je me suis mis sur mon projet, j'en avais pas trouvé qui me plaisaient.  
Adodb a l'air de roxer sa maman, j'ai presque envie de modifier mon projet à la volée lol.
Bon bah après avoir un peu regardé, cette classe fait tout ce dont j'ai besoin.
Le seul truc qui me manque (mais c'est ptet dedans), ça serait de pouvoir faire au sein d'une transaction des requetes qui peuvent planter sans annuler la transaction.
Et j'aimerais bien pouvoir empecher la base d'accepter de nouvelles requetes quand une requete plante (mais comme pour les transactions, que ça soit paramétrable).
 
Tu saurais si ce que je veux faire est facilement faisable avec cette classe ?

Reply

Marsh Posté le 28-04-2006 à 12:04:48    

j'ai pas très bien compris ton problème :o
en gros tu as par exemple:


requete 1: insert ...
requete 2: insert ...
requete 3: update ...
requete 4: insert ...
requete 5: update ...


Et tu voudrais que si la requête 4 "plante", tu n'executes pas la 5 mais que les résultats produient par les 1,2 et 3 restent dans la base ou au contraire ne soient pas pris en compte?

Reply

Marsh Posté le 28-04-2006 à 12:57:38    

j'aimerais deux choses :  
 
- si la requete 4 plante, qu'on continue normalement, et sans annuler la transaction en cours
- si la requete 4 plante, la transaction en cours est annulée (ça aucun problème), mais plus aucune requete ne s'execute ensuite

Reply

Marsh Posté le 28-04-2006 à 13:51:50    

http://www.phpscripts-fr.net/scrip [...] ration+BDD
http://www.comscripts.com/scripts/ [...] s.sc1.html
http://sourceforge.net/projects/alyoop


Message édité par Sve@r le 28-04-2006 à 14:03:31

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-04-2006 à 14:01:55    

Bon sinon, j'ai matté la doc de ADODB (elle est très bien fait faut reconnaitre). Malheureusement, plusieurs points ne me donne pas envie de l'utiliser :  
 
- un faible support de mysql 5, par exemple au niveau des procédures stockées.
- je voyais un intéret énorme en terme de portabilité. Et puis en fait non, cf les propres liens de ADODB : http://phplens.com/lens/adodb/tips_portable_sql.htm  
Regardez la section 'SQL as a Localization Exercise'. Donc en gros ils te disent que pour être sur d'assurer une bonne portabilité, tu dois inclure des requêtes spécifiques à chaque bdd. Donc au final la portabilité elle est de 0 quoi.
Etant donné que j'ai déjà un "switcher" de base de données, si je dois réécrire les requetes, ça me coutera rien de plus de modifier également ma classe d'accès à la base.
(ADODB est très bien hein, simplement pour utiliser des fonctionnalités avancées des bdd, bah ils y peuvent rien mais c'est pas portable quoi).
 
Au final, l'intérêt que je vois à utiliser cette classe est que ça "standardise" l'accès à ta bdd, d'autres développeurs n'étant pas perdu s'ils ont déjà utilisé cette librairie. Mais au final, à part ça ...
Donc je préfère ma propre classe, qui inclue les fonctionnalités que j'aime, ni plus, ni moins. Je la commente un peu et je la poste comme convenu.

Message cité 2 fois
Message édité par Djebel1 le 28-04-2006 à 14:04:23
Reply

Marsh Posté le 28-04-2006 à 14:23:05    

Djebel1 a écrit :

j'aimerais deux choses :  
 
- si la requete 4 plante, qu'on continue normalement, et sans annuler la transaction en cours
- si la requete 4 plante, la transaction en cours est annulée (ça aucun problème), mais plus aucune requete ne s'execute ensuite


Pour moi, rien a voir avec la gestion des transactions. C'est plus de la gestion d'erreurs au sein de celles-ci et c'est le developpeur qui doit s'y coller ;)
 
 

Djebel1 a écrit :


- je voyais un intéret énorme en terme de portabilité. Et puis en fait non, cf les propres liens de ADODB : http://phplens.com/lens/adodb/tips_portable_sql.htm
Regardez la section 'SQL as a Localization Exercise'. Donc en gros ils te disent que pour être sur d'assurer une bonne portabilité, tu dois inclure des requêtes spécifiques à chaque bdd. Donc au final la portabilité elle est de 0 quoi.


Bin c'est sur que si tu utilises du SQL 'spécifique' à une BDD, la portabilité tu peux oublier [:spamafote]
 
 

Djebel1 a écrit :

Donc je préfère ma propre classe, qui inclue les fonctionnalités que j'aime, ni plus, ni moins. Je la commente un peu et je la poste comme convenu.


L'argument ultime: "c'est moi qui l'a fait donc c'est mieux" :o

Message cité 1 fois
Message édité par anapajari le 28-04-2006 à 14:24:13
Reply

Marsh Posté le 28-04-2006 à 14:27:43    

Djebel1 a écrit :

Donc je préfère ma propre classe, qui inclue les fonctionnalités que j'aime, ni plus, ni moins. Je la commente un peu et je la poste comme convenu.


C'est pour ca que j'ai développé la mienne ^^
Maintenant j'ai implémenté les jointures, j'ai passé la matinée a potasser les JOIN...
Utilisez vous plus INNER ? LEFT ? ou RIGHT ?

Reply

Marsh Posté le 28-04-2006 à 15:28:41    

anapajari a écrit :


L'argument ultime: "c'est moi qui l'a fait donc c'est mieux" :o


pas du tout : c'est mieux pour moi car ça répond à mes besoins.
En fait j'en ai marre de devoir gérer les erreurs. Je me suis fait une classe qui me permet de ne plus jamais avoir à tester l'erreur provoquée par une requete. Et franchement, c'est la seule et unique raison pour laquelle je ne vais pas utiliser ADODB. Et j'ai bien souligné que je trouvais cette librairie très bien, mais que problème de portabilité pour problème de portabilité, je préfère faire chier le développeur suivant que moi :D

Reply

Marsh Posté le 28-04-2006 à 15:29:50    

Citation :

si tu utilises du SQL 'spécifique' à une BDD


Le problème étant que pour certains trucs t'es obligé :/
edit : putain de bouton editer

Message cité 1 fois
Message édité par Djebel1 le 28-04-2006 à 15:30:49
Reply

Marsh Posté le 28-04-2006 à 15:36:51    

Djebel1 a écrit :

Le problème étant que pour certains trucs t'es obligé :/
edit : putain de bouton editer


Oui... Par exemple l'attribut LIMIT ne passe pas sous oracle :sweat:

Reply

Marsh Posté le 28-04-2006 à 15:49:59    

bah ca encore ça va, ADODB te permet de gérer ce genre de problème. C'est pour les trucs pour lesquels ADODB n'a pas d'abstraction le problème

Reply

Marsh Posté le 28-04-2006 à 16:05:53    

Voilà je vous soumets ma classe d'accès à une base MySQL :  
 
Les intérêts qu'elle a pour moi (d'ailleurs c'est marrant, j'ai inclue des fonctionnalités qui se trouve dans ADODB :p)
 
- Gestion du debug : 3 niveaux de debug configurable : 1 pour voir toutes les requetes, 1 pour voir uniquement les requetes échouées, 1 pour la phase de prod
- Gestion du debug : mise dans un fichier log des erreurs mysql
- Gestion des transactions : le gestionnaire permet de ne pas imbriquer par erreur plusieurs transactions. Rollback toute transaction non confirmée à la fin de votre script.
- le test du retour des requêtes devient inutile : si une requete échoue, toute transaction sera automatiquement annulée, et la base n'acceptera plus aucune requete. Vous pouvez donc sereinement balancer une serie de requetes sans avoir à verifier la présence d'erreur. A la fin de votre "procédure", il vous suffit de vérifier en une seule instruction si une erreur s'est produite.
Un paramètre optionnel permet de ne pas obtenir ce comportement : une requete échouée ne provoquera pas l'annulation de la transaction, et la base continuera d'accepter des requêtes.
- multiton pattern : votre classe est appelable de n'importe où, et vous garantit la présence d'une seule instanciation en mémoire par connection. Vous pouvez gérer plusieurs connexions simultannées.
- pas de trucs compliqués pour gêrer les requetes, vous pouvez donc toutes les faire. Bien sur, cela implique que si vous changez de bdd, il faudra réécrire les requetes dans votre couche de persistance. Mais comme de toute façon si vous changez de bdd vous devrez réécrire vos requetes ... (comme on en a discuté, une abstraction totale de la bdd est impossible)
 

Code :
  1. <?php
  2. /**
  3. * Database access class
  4. *  
  5. * All requests to the database are channeled through this class.
  6. * This lets you easily change the database or debug applications.
  7. * This class is a multiton. It can be instantiated from anywhere.
  8. *  
  9. * @package Database
  10. * @category General
  11. * @version 1. (04/2006)
  12. */
  13. class Database
  14. {
  15.     /**
  16.     * array that contains Database objects resources.
  17.     * this array is static (this class is a multiton)
  18.     */   
  19.     private static $_arrObjDatabase;
  20.     /**
  21.     * link identifier to the current database
  22.     */
  23.     private $_link;
  24.     /**
  25.     * variable needed by the transactManager function
  26.     * @see Database::transactManager()
  27.     */
  28.     private $_transactManager;
  29.     /**
  30.     * variable needed by the transactManager function
  31.     * @see Database::transactManager()
  32.     */
  33.     private $_rollback;
  34.     /**
  35.     * this var indicates whether the database keep on  
  36.     * accepting queries or not.
  37.     */
  38.     private $_acceptQuery;
  39.     /**
  40.     * debug level, var needed by the _debug function
  41.     * @see Database::_debug()
  42.     */
  43.     private $_debug;
  44.     /**
  45.     * files in wich the mysql errors have to be logged,  
  46.     * var needed by the _debug function
  47.     * @see Database::_debug()
  48.     */
  49.     private $_dirLogError;
  50.     /**
  51.     * private constructor (multiton pattern)
  52.     */
  53.     private function __construct()
  54.     {
  55.         $this->_transactManager = 0;
  56.         $this->_rollback = 0;
  57.         $this->_acceptQuery = true;
  58.         //value to change for application debug
  59.         $this->_debug = 2;
  60.         $this->_dirLogError = 'error.log';
  61.     }
  62.     /**
  63.     * function that instantiates the Database object, but only if it does not already exist (multiton pattern).
  64.     *  
  65.     * @param string $login              login to connect to database
  66.     * @param string $password           password to connect (not encrypted)
  67.     * @param string $base               database to choose
  68.     * @param string $host               database server
  69.     * @return resource                  resource to Database object
  70.     */
  71.     public static function connection($login = 'defaultLogin', $password = 'defaultPass',
  72.                                       $base = 'defaultDb', $host = 'defaultHost')
  73.     {
  74.         $temp = $login.$base.$host;
  75.         //$temp to let us know if this object is already instantiated or not
  76.         if (!isset(self::$_arrObjDatabase[$temp])) {
  77.             self::$_arrObjDatabase[$temp] = new Database();
  78.         }
  79.         //if self::$_arrObjDatabase[$temp]->_link doesn't exist (no connection, object has just been instantiated)
  80.         //or is negative (connection closed by using $this->close), connection to database
  81.         if (!isset(self::$_arrObjDatabase[$temp]->_link) || self::$_arrObjDatabase[$temp]->_link == -1) {
  82.             self::$_arrObjDatabase[$temp]->_setStatut(self::$_arrObjDatabase[$temp]->_mysqlConnection($login, $password, $base, $host));
  83.         }
  84.      
  85.         return self::$_arrObjDatabase[$temp];
  86.     }
  87.     /**
  88.     * connection and choice of the database
  89.     *  
  90.     * @param string $login              login to connect to database
  91.     * @param string $password           password to connect (not encrypted)
  92.     * @param string $base               database to choose
  93.     * @param string $host               database server
  94.     * @return mixed                     link identifier on succes, false on error
  95.     */
  96.     private function _mysqlConnection($login, $password, $base, $host)
  97.     {
  98.         $test = mysql_connect($host, $login, $password);
  99.         $this->_debug('Connection to database', $test, 1);
  100.         if ($test === false) {
  101.             return $test;
  102.         } else {
  103.             $select_db = mysql_select_db($base, $test);
  104.             $this->_debug('Database choice', $select_db, 1);
  105.             if (!$select_db) {
  106.                 return $select_db;
  107.             }
  108.         }
  109.         //if everything is alright, return link identifier
  110.         return $test;
  111.     }
  112.     /**
  113.     * close connection to database
  114.     */
  115.     public function close()
  116.     {
  117.         if ($this->_link > 0) {
  118.             $close = mysql_close ($this->_link);
  119.             $this->_debug('Close connection', $close, 1);
  120.             if ($close) $this->_setStatut(-1);
  121.         }
  122.     }
  123.     private function _setStatut($value)
  124.     {
  125.         $this->_link = $value;
  126.     }
  127.     /**
  128.     * to know if a mysql error occured
  129.     *
  130.     * @return bool      true if an error occured, else false
  131.     */
  132.     public function getError()
  133.     {
  134.         if (!$this->_acceptQuery) {
  135.             return true;
  136.         } else {
  137.             return false;
  138.         }
  139.     }
  140.     /**
  141.     * manage and debug queries to database
  142.     *  
  143.     * The query will be sent to the database only if  
  144.     * $this->_acceptQuery is set to true.
  145.     *  
  146.     * @param string $query      query to send to database
  147.     * @param bool $forceQuery   if set to false (default value),  
  148.     *                           a failed query will rollback current transaction,  
  149.     *                           and force the database to reject following queries.
  150.     *                           If set to true and the query failed, nothing will happen.
  151.     * @return mixed             resource on succes, false on error
  152.     */
  153.     public function request($query, $forceQuery = false)
  154.     {
  155.         $resource = false;
  156.         if ($this->_acceptQuery) {
  157.             $resource = @mysql_query($query, $this->_link);
  158.             $this->_debug($query, $resource, $forceQuery);
  159.         }
  160.         return $resource;
  161.     }
  162.     /**
  163.     * Fetch a result row as both an associative array and a numeric array (mysql_fetch_array) .
  164.     *  
  165.     * if they are no more rows, the results are free (mysql_free_result)
  166.     *  
  167.     * @param resource $resource     resource from a call to $this->request (mysql_query)
  168.     * @param mixed                  array while there is a result, false if there is no more rows
  169.     */
  170.     public function fetch_array($resource)
  171.     {
  172.         if ($resource !== false) {
  173.             $result = mysql_fetch_array($resource);
  174.             if ($result === false) {
  175.                 mysql_free_result($resource);
  176.             }
  177.             return $result;
  178.         } else {
  179.             return false;
  180.         }
  181.     }
  182.     /**
  183.     * get number of results for a select command
  184.     *  
  185.     * The query will be sent to the database only if  
  186.     * $this->_acceptQuery is set to true.
  187.     *  
  188.     * @param resource $resource     resource from a call to $this->request (mysq_query)
  189.     * @param bool $forceQuery       if set to false (default value),  
  190.     *                               a failed query will rollback current transaction,  
  191.     *                               and force the database to reject following queries.
  192.     *                               If set to true and the query failed, nothing will happen.
  193.     * @return mixed                 number of results (int) on succes, false on error
  194.     */
  195.     public function numberSelect($resource, $forceQuery = false)
  196.     {
  197.         $count = false;
  198.         if ($this->_acceptQuery) {
  199.             $count = @mysql_num_rows($resource);
  200.             $this->_debug('Query number of results', $count, $forceQuery);
  201.         }
  202.         return $count;
  203.     }
  204.     /**
  205.     * get number of affected rows by an insert, delete or update command
  206.     *  
  207.     * The query will be sent to the database only if  
  208.     * $this->_acceptQuery is set to true.
  209.     *  
  210.     * @param resource $resource       resource from a call to $this->request (mysq_query)
  211.     * @param bool $forceQuery         if set to false (default value),  
  212.     *                                 a failed query will rollback current transaction,  
  213.     *                                 and force the database to reject following queries.
  214.     *                                 If set to true and the query failed, nothing will happen.
  215.     * @return mixed                   number of affected rows (int) on succes, false on error
  216.     */
  217.     public function numberAffected($forceQuery = false)
  218.     {
  219.         $count = false;
  220.         if ($this->_acceptQuery) {
  221.             $count = @mysql_affected_rows($this->_link);
  222.             $this->_debug('Query number of affected rows', $count, $forceQuery);
  223.         }
  224.         return $count;       
  225.     }
  226.     /**
  227.     * get last auto-increment ID
  228.     *  
  229.     * The query will be sent to the database only if  
  230.     * $this->_acceptQuery is set to true.
  231.     *  
  232.     * @param bool $forceQuery         if set to false (default value),  
  233.     *                                 a failed query will rollback current transaction,  
  234.     *                                 and force the database to reject following queries.
  235.     *                                 If set to true and the query failed, nothing will happen.
  236.     * @return mixed $id       last auto_increment ID (int) on succes, false on error
  237.     */
  238.     public function insertId($forceQuery = false)
  239.     {
  240.         $id = false;
  241.         if ($this->_acceptQuery) {
  242.             $id = @mysql_insert_id($this->_link);
  243.             $this->_debug('Query last auto_increment ID', $id, $forceQuery);
  244.         }
  245.         return $id;
  246.     }   
  247.     /**
  248.     * manage transactions
  249.     *  
  250.     * @param string $action        action to be proceed (begin transaction, commit or rollback transaction)
  251.     * @param string $level         level of the transaction, default value serializable
  252.     */
  253.     public function transactManager($action, $level='serializable')
  254.     {
  255.         switch ($action) {
  256.         case 'begin' :
  257.             //if a second transaction is interleaved,  
  258.             //the first one will not be stopped
  259.             if ($this->_transactManager == 0) {
  260.                 if ($level == 'read uncommitted' ||
  261.                     $level == 'read committed'   ||
  262.                     $level == 'repeatable read'  ||
  263.                     $level == 'serializable') {
  264.        
  265.                     $this->request('set transaction isolation level '.$level);
  266.                 }
  267.                 $this->request('start transaction');
  268.             }
  269.             $this->_transactManager ++;
  270.             break;
  271.         case 'rollback' :
  272.             //if try to rollback a transaction interleaved by error,  
  273.             //wait for the end of the first one, and then rollback all of them.
  274.             if ($this->_transactManager > 1) {
  275.                 $this->_rollback = 1;
  276.             } elseif ($this->_transactManager == 1) {
  277.                 $this->request('rollback');
  278.                 $this->_rollback = 0;
  279.             }
  280.             if ($this-> _transactManager > 0) {
  281.                 $this->_transactManager --;
  282.             }
  283.             break;
  284.         case 'commit' :
  285.             //commit is allowed only if no interleaved transaction was rollbacked
  286.             if (($this->_transactManager == 1) and ($this->_rollback == 0)) {
  287.                 $this->request('commit');
  288.             } elseif (($this->_transactManager == 1) and ($this->_rollback == 1)) {
  289.                 $this->request('rollback');
  290.                 $this->_rollback = 0;
  291.             }
  292.             if ($this->_transactManager > 0) {
  293.                 $this-> _transactManager --;
  294.             }
  295.             break;
  296.         }
  297.     }
  298.     /**
  299.     * Debug function
  300.     *  
  301.     * Display all database queries, failed database queries, or any,  
  302.     * depending on the debug level in the class constructor.
  303.     * Debug all queries.
  304.     *  
  305.     * @param string $query                  query to database
  306.     * @param resource $resourceResult       resource from a query to database (mysql_query, mysql_insert_id, ...)  
  307.     * @param bool $forceQuery               if this var is false and the query has failed,  
  308.     *                                       current transaction will be rollbacked, error will be logged,  
  309.     *                                       and database will reject all following queries.
  310.     *                                       if this var is true, nothing happens.   
  311.     */
  312.     private function _debug($query, $resourceResult, $forceQuery = 0)
  313.     {
  314.         //depending on the debug level
  315.         if ($this->_debug == 2) {
  316.             //all queries are shown, not to use in production
  317.             if ($resourceResult === false) {
  318.                 echo 'FAILED quey : <br />';
  319.             } else {
  320.                 echo 'valid query : <br />';
  321.             }
  322.             echo htmlentities($query), '<br /><br />';
  323.         } elseif ($this->_debug == 1) {
  324.             //only failed queries are shown, not to use in production
  325.             if ($resourceResult === false) {
  326.                 echo 'FAILED query : <br />', htmlentities($query), '<br /><br />';
  327.             }
  328.         } else {
  329.             //production version
  330.         }
  331.         //log the errors
  332.         if ($resourceResult === false && !$forceQuery) {
  333.             //rollback transaction, no more queries will be accepted
  334.             $this->transactManager('rollback');
  335.             $this->_acceptQuery = false;
  336.             //write error in log file
  337.             $text = 'The query : '.$query."\r\n".'has returned the error : '.mysql_error($this->_link)."\r\n";
  338.             $handle = @fopen($this->_dirLogError, 'ab');
  339.             if ($handle) {
  340.                 @fwrite($handle, $text);
  341.             }
  342.         }
  343.     }
  344.     /**
  345.     * protect queries to database
  346.     *  
  347.     * @param mixed $value       value to protect
  348.     * @return mixed $value      value protected
  349.     */
  350.     public function quoteSmart($value)
  351.     {
  352.         //stripslashes
  353.         if (get_magic_quotes_gpc()) {
  354.             $value = stripslashes($value);
  355.         }
  356.         //protection if not real     
  357.         if (!is_numeric($value)) {
  358.             $value = mysql_real_escape_string($value);
  359.         }
  360.         return $value;
  361.     }
  362.    
  363.     public function __destruct()
  364.     {
  365.         //rollback all transactions not finished
  366.         if ($this->_transactManager > 0) {
  367.             $this->request('rollback');
  368.         }
  369.     }
  370. }
  371. ?>


Message édité par Djebel1 le 28-04-2006 à 16:28:36
Reply

Marsh Posté le 28-04-2006 à 17:16:04    

moi j'aurais fais une fonction startTransaction, rollback et commit, a la place transactionManager
 
Parce que ton switch, tu fais une faute de frappe dans $action, il va pas te dire que ça marche pas (quoique, y'a pas de default).


---------------
my flick r - Just Tab it !
Reply

Marsh Posté le 28-04-2006 à 17:36:51    

t'as pas tort, je le modifierai

Reply

Marsh Posté le 29-04-2006 à 00:59:15    

Sinon ya les classes mysqli et PDO (qui implémente un drivers pour sqlite, oracle, pgsql et mysql) et qui sont inclus dans PHP5 :)

Reply

Marsh Posté le 29-04-2006 à 10:20:28    

the_bigboo a écrit :

Maintenant j'ai implémenté les jointures, j'ai passé la matinée a potasser les JOIN...
Utilisez vous plus INNER ? LEFT ? ou RIGHT ?


 
Ca dépend totalement du type de requête voulu.
Exemple simple: 2 tables liées par une relation 0/1 vers n style voiture-marque (avec certaines voitures sans marque, bon je trouve rien deplus pertinent)
Si tu requêtes toutes les voitures avec leur marques dans une requête avec jointure simple (style "from voiture, marque where voiture.marque=marque.id" ), tu n'obtiendras que les voitures ayant une marque (que les voitures où l'identifiant "marque" est rempli) et ça n'affichera pas les voitures sans marque.
Si ton but est d'obtenir toutes les voitures, et d'afficher en plus la marque pour les voitures qui en ont une, alors faut demander un "outer join".
Pour les "left" et "right", c'est aussi d'autres caractéristiques correspondant à d'autres pb similaires. On peut pas dire qu'il faut toujours du left ou toujours du right...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-04-2006 à 18:57:47    

Sve@r a écrit :


Si ton but est d'obtenir toutes les voitures, et d'afficher en plus la marque pour les voitures qui en ont une, alors faut demander un "outer join".
Pour les "left" et "right", c'est aussi d'autres caractéristiques correspondant à d'autres pb similaires. On peut pas dire qu'il faut toujours du left ou toujours du right...


Pourquoi pas INNER ?

Reply

Marsh Posté le 29-04-2006 à 19:04:28    

Et pourquoi pas regarder un cour sur les jointures ?

Reply

Marsh Posté le 30-04-2006 à 01:24:49    

qq idées en vrac:
 
J'ai découvert le bind de valeurs avec Qt:

Code :
  1. QSqlQuery query;
  2.     query.prepare( "INSERT INTO atable (id, forename, surname) "
  3.                    "VALUES (:id, :forename, :surname)" );
  4.     query.bindValue( ":id", 1001 );
  5.     query.bindValue( ":forename", "Bart" );
  6.     query.bindValue( ":surname", "Simpson" );
  7.     query.exec();


C'est peut être le truc le plus interessant.
 
Sinon, ça me paraît un poil compliqué. J'ai pas tout lu, mais de loin ça ressemble à un nid à bugs. Quand tu jongle bien avec le SQL (qui finalement n'est pas très compliqué) tu peut te passer de la plupart des fonctionnalités ci-dessus.
 
Ce qui est paraît interessant, c'est la gestion des plantages. Mais j'en connais pas qui soit vraiment utile dans tous les cas.
 
Un autre truc que j'utilise souvent: une liste de conditions de longueur variable comme dans une page de recherche avec champs facultatifs.
 
Finalement, ce que je préfère, c'est une classe à part pour encapsuler les requêtes, selon les objets et la base. Je trouve ça plus facile à débugger.

Reply

Marsh Posté le 04-05-2006 à 09:36:43    

c'est pour ca que j'ai fait cette class ! Mes besoins sont pas extraordinaires !elle est adaptée a mes besoins et c'est pratique c'est tout ;)

Reply

Marsh Posté le 04-05-2006 à 09:51:54    

Je@nb a écrit :

Sinon ya les classes mysqli et PDO (qui implémente un drivers pour sqlite, oracle, pgsql et mysql) et qui sont inclus dans PHP5 :)


Attention toutefois à PDO, qui n'est pas une librairie d'abstraction de source de donnée, mais une librairie d'abstraction d'accès aux donnée. Si on code en PDO pour mysql et qu'on fait pas gaffe, y'a de forte chance qu'il faille réécrire toutes les requêtes lors du passage à un autre systus.
 
AdoDb, par contre, est vraiment un machin d'abstraction de bidule, à savoir que toutes les requêtes sont écrites une fois pour toutes, qu'on soit sous MySql, Oracle, etc.

Reply

Marsh Posté le 04-05-2006 à 09:53:32    

the_bigboo a écrit :

voila j'ai fait cette petite class en PHP5 car je trouve que meme si c'est assez facile de gérer ses requetes SQL, c'est bien pratique car le code en est d'autant plus simplifié. Elle fait tout de meme 650 lignes :)
 
[...]
 

Code :
  1. <?php
  2. // Librairie MySQL optimisée PHP5
  3. class MySQL {
  4. [....]
  5. }
  6. // Class annexes - Insert
  7. class MySQL_insert extends MySQL {
  8. [....]
  9. }
  10. ?>



 
J'aurais pas utilisé extends pour MySQL_insert, j'aurais plutôt mis un objet MySql dans MySQL_insert

Reply

Marsh Posté le 04-05-2006 à 11:17:22    

probablement, mais l'objet MySQL sert pour d'autres objets aussi... Notament pour charger la configuration.

Reply

Marsh Posté le 04-05-2006 à 11:20:47    

Là je pense qu'il y a un problème de structure. Tu utilises extends pour utiliser les fonctionnalités de MySQL. MySQL_Insert n'est pas un objet de type MySQL, c'est un objet qui utilise MySQL. You failed :D Essaye de revoir tes notions de l'orienté objet :)

Reply

Marsh Posté le 04-05-2006 à 11:43:23    

FlorentG a écrit :

Là je pense qu'il y a un problème de structure. Tu utilises extends pour utiliser les fonctionnalités de MySQL. MySQL_Insert n'est pas un objet de type MySQL, c'est un objet qui utilise MySQL. You failed :D Essaye de revoir tes notions de l'orienté objet :)


ben tu ferais ca comment toi ? Je vois pas d'autres moyens ! Si je déclare un objet dans l'objet ca va faire du copier/coller de ouf !
En quoi est-ce une faute puisque ca marche tres bien comme ca ??

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed