Aller au menu - Aller au contenu
Inscris-toi au e-camp "Héberge ton jeu Facebook sur Azure" de Microsoft vendredi 25 mai à 13h30 !

POO - Debutant

Je commences à comprendre ?

Pour accéder à cette section
Connectez-vous !
connexion_rpx

Résolu Le problème de ce sujet a été résolu

Offre d'emploi : Développeur Web PHP/Drupal (H/F)

Page 1  2  3  4  ...  11  12  13  14  Suivante
Auteur Message
1 visiteur sur ce sujet (1 Anonyme)
Page 1  2  3  4  ...  11  12  13  14  Suivante
Hors ligne squall6969 # Posté le 13/10/2008 à 17:44:40
Avatar

Études : AFIP

Bonjour tout le monde,

Décidé à comprendre et faire bon usage de la programmation orientée objet en php, voici mon hypothèse réalisé grâce au critiques de Tracker ;)

une classe validation:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
abstract class isValid{
     protected $err = "";

     abstract function isValid(){}
     
     public function getErr(){
          return $this->err;
     }

}
?>


Si j'ai bien compris, nous serons obligé d'implémenter la méthode isValid() puisque elle est définie en abstract, ce qui permet de controller l'implémentation de la méthode.

Ensuite je suis perdu... :(

En fait Tracker m'a reproché de confondre heritage avec utilisation (Et il à raison), mais alors dans le cas présent, si je veux imaginons controller une adresse mail au sein d'une classe, dois-je créer une classe isValidMail qui implémenterait juste la classe validation ?

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?php
class isValidMail extends isValid{

private $mail;

     public __construct($mail){
          $this->mail = $mail;
     }
     
     //j'implémente la fonction isValid de la classe mère
     public function isValid(){
          if(preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $this->mail)==false){
          $this->$err = "l'adresse e-mail est invalide";
          return false;
          }
          return true;
     }

}
?>


Déjà je voudrais savoir si je suis sur la bonne voix (J'accepte toutes les critiques qui puissent me faire avancer)

Si c'est pas trop mal, comment créer on par la suite une classe qui se servirait de plusieurs méthodes de différentes class ? sera t-on obliger de réinstancier les classes utiles au seins des classes?( dans le but justement de ne pas confondre héritage et utilisation ? )

Un grand merci d'avance :)
Édité le 13/10/2008 à 17:45:19 par squall6969
 
Publicité # Posté le 13/10/2008 à 17:44:40

Hors ligne Tracker # Posté le 13/10/2008 à 17:58:03
Avatar

Études : Université de Lyon

Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Oui c'est parfait ;)

Tu pourrais même éviter de faire un constructeur, et passer la valeur à valider à la méthode isValid(...), l'objet étant capable de retenir la nature de la dernière erreur...

Dernière chose, le nom de ta classe... c'est une chose que tu es en train de décrire donc "isValid" c'est plutôt n'importe quoi comme nom de chose, non ? c'est un truc qui sert à valider, donc appelle ça un Validateur et par extension un ValidateurDeMail !!! (les noms en français ça pue un peu en développement).


[ed]
En fait, faut aller un peu plus loin encore, et sépare la notion de champ et la notion de validateur, un champ contenant une valeur et des validateurs... le champ et valide si ses validateurs sont heureux ;)


Tracker.
Édité le 13/10/2008 à 18:12:40 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 13/10/2008 à 18:13:49
Avatar

Études : AFIP

Ok merci pour ces conseils, j'aurais tout de même un question:

Du cous je vois comment m'y prendre pour structurer mais quelle est l'utilitée finalement de la classe Validateur ?

Est-ce que son utilité aurait été nulle si je n'avais pas mis la fonction getErr() ?

Alors pour l'utilisation de la classe, j'instancierais donc la classe fille validateurDeMail et imaginons que j'ai un validateurDeTelephone n'y aura t'il qu'une seule instance de la classe mère ou 2 ?(je suppose 2)

AH je crois que j'ai compris : il y aura deux instances , qui garderons en mémoire la dernière erreure obtenu


PS: que me conseille tu de faire Tracker pour maitriser un peu mieux le sujet ?


MERCI :D

[EDIT]
Ok je vais essayer de pousse un peu plus loin dans la soirée et apporter une nouvelle solution plus réfléchi
Édité le 13/10/2008 à 18:23:24 par squall6969
 
Hors ligne Tracker # Posté le 13/10/2008 à 19:28:56
Avatar

Études : Université de Lyon

Son utilité c'est de valider... et pas forcement dans le contexte d'un champ de formulaire, car y'a plein de trucs qui doivent être validés systématiquement... Et c'est pas la peine de re-développer 500x la même logique de validation, suffit de créer une dizaine de classes une fois pour toute... RegexValidator, ValueValidator, StringLengthValidator etc...

Pour le reste apparemment tu as compris...


Tracker.
Édité le 13/10/2008 à 19:30:44 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 14/10/2008 à 13:51:00
Avatar

Études : AFIP

Ok,

Alors voici mon essai

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
abstract class Validator{
     protected $err = "";

     abstract function isValid(){}
     
     public function getErr(){
          return $this->err;
     }

}
?>


Et voici la classe hérité qui verifie que on a bien une chaine de caractères

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?php
class ValidatorString extends Validator{
    

     public function isValid($var){
          if($var !== string){
               $this->err = "La variable ne contient pas une chaîne de caractères.";
                return false;
          }
          return true;
     }
     
}
?>


Et voici la dernière étape

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class ValidatorStringValue extends ValidatorString{
    

     public function isValid($var,$var2){
          if(parent::isValid($var)&& parent::isValid($var2)){
               if($var==$var2){
                    return true;
               }   
               else{
                    $this->err = "Les deux chaines de caractère ne correspondent pas.";
                    return false
               }  
          }        
          else{
               return false;
          }
     }
    
}
?>


Il me semble que je respecte la structure POO et je comprends l'intérêt dans la classe ValidatorStringValue.

En effet lorsque le premier test echoue "if(parent::isvalid($var)&& parent::isvalid($var2))", on a pas besoin de redéfinir le message d'erreur.

On va donc pouvoir créer une succession de classe logique avec le minimum de dépendance possible et le plus de cohésion possible.

J'espère que mon exemple est bon et ma compréhension aussi :D
Édité le 14/10/2008 à 13:55:36 par squall6969
 
Hors ligne Tracker # Posté le 14/10/2008 à 14:15:09
Avatar

Études : Université de Lyon

Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Citation
[...]Il me semble que je respecte la structure POO [...]


En fait non,
tu dois avoir quelque chose comme:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php
abstract class Validator
{
  abstract public function isValid($value);
  // [...]
}

class StringLengthValidator extends Validator
{
  // [...] manque le constructeur

  public function isValid($value)
  {
    $l = strlen($value);
    return !( ($l>$this->_max) || ($l<$this->_min) );
  }

  // [...]
}


Tes méthodes isValid doivent obligatoirement avoir la même signature (nombre d'arguments de la méthode) sinon ce n'est pas une implémentation (et tu casses la notion de polymorphisme)

Concrètement on utilise le validateur comme ça:

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php

$v = new StringLengthValidator(0,15);
if( $v->isValid($ma_chaine_a_tester) )
{
  //...
}
else
{
  //...
}


[ed]
Dans le contexte d'un formulaire on écrirait des choses comme:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<?php
// [...]

$fld = new TextField('Url');
$fld->addValidator( new StringLengthValidator(0, 1500) );
$fld->addValidator( new RegexpValidator('#^http://([^/]+)(/.*)?$') ); // c'est un exemple ;)
$form->addField($fld);

// [...]

// Avec pour objectif d'écrire:

$form->render(); // production html du formulaire
//ou
$form->isValid($_POST); // validation et récupération des valeurs clientes.


Tracker.
Édité le 14/10/2008 à 14:34:05 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 14/10/2008 à 14:35:06
Avatar

Études : AFIP

Ok alors voici mon nouvel essai (Merci pour ton aide pédagogique, tu ne donnes pas la solution toute faites et sa me permet de te montrer que je m'implique :D )

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
abstract class Validator{
     protected $err = "";

     abstract function isValid($var){}
     
     public function getErr(){
          return $this->err;
     }

}

class ValidatorString extends Validator{
    

     public function isValid($var){
          if($var !== string){
               $this->err = "La variable ne contient pas une chaîne de caractères.";
                return false;
          }
          return true;
     }
     
}

class ValidatorStringValue extends ValidatorString{
    
     private $varServantDeComparateur ;

     public function __construct($var2){
          $this->varServantDeComparateur = $var2;
     }  
   
     public function isValid($var){
          if(parent::isValid($var)&& parent::isValid($varServantDeComparateur )){
               if($var==$varServantDeComparateur ){
                    return true;
               }   
               else{
                    $this->err = "Les deux chaines de caractère ne correspondent pas.";
                    return false
               }  
          }        
          else{
               return false;
          }
     }
    
}




?>


En esperant qu' il y ait une évolution dans le code par rapport au précédent :D
 
Hors ligne Tracker # Posté le 14/10/2008 à 14:40:45
Avatar

Études : Université de Lyon

Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
$var !== string je pense pas que ça veuille dire quelque chose,
et manque un $this dans $varServantDeComparateur, sinon l'archi est bonne.

Maintenant réfléchis plutôt aux types de validateurs qu'il serait nécessaire de produire pour couvrir tous les cas de validation (du moins la plupart).

- ValidatorString -> boff, tout ou presque pouvant être une chaine
- ValidatorStringValue -> boff, comparer deux valeurs c'est un cas particulier

Par contre savoir si $var est numérique, ou que sa longueur est comprise entre un min et un max, ou si sa valeur est plus ou moins grande que, savoir si $var n'est pas null ou vide, etc...
Fais une liste, après on votera ;)


Tracker.
Édité le 14/10/2008 à 14:45:01 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne Jérémy_B # Posté le 14/10/2008 à 15:02:56
Avatar

Désolé de déranger votre conversation, qui plus est, est vraiment très intéressante et instructive, j'ai une toute petite question niveau compréhension, par rapport au code qu'à déposer Tracker :

Code : PHP
1
2
3
4
5
6
<?php
$fld = new TextField('Url');
$fld->addValidator( new StringLengthValidator(0, 1500) );
$fld->addValidator( new RegexpValidator('#^http://([^/]+)(/.*)?$') ); // c'est un exemple ;)
$form->addField($fld);
?>


Tu instancies ta première classe qui est TextField en lui entrant un paramètre, puis tu entres dans la méthode addValidator () un paramètre qui est en faite une instance de classe nommé StringLengthValidator(). Je voulais savoir comment on appelle ce type de "système", imbrication d'instance de classe ..?

En tout cas, avec vos messages que je lis depuis le début, je comprend mieux la puissance de l'OO (si on peut dire ça comme ça) qu'avec des tutoriaux (même s'ils sont là pour nous apprendre les notions). Je comprend mieux la notion de maintenabilité dans le faite que chaque classe a sa propre logique, fait sa propre action et pas autre chose.

Je continurai donc à suivre ce sujet fort intéressant. D'ailleurs, Tracker, je trouve que tes questions sont vraiment pédagogiques. Tu nous forces en quelque sorte à réfléchir comme il faut, et comme dans ton message précédent, tu pousses la réflection. Excellent pour apprendre l'OO.
Hors ligne Tracker # Posté le 14/10/2008 à 15:11:31
Avatar

Études : Université de Lyon

Citation
[...] imbrication d'instance de classe ..?

Avec un œil statique ça pourrait s'appeler comme ça, mais si on prend en compte l'aspect dynamique du système c'est plutôt de l'utilisation. Les objets s'inter-utilisent à partir du moment ou ils se connaissent / se possèdent. Pour faire court c'est ce qu'on appelle la poo ;)


Tracker.
Édité le 14/10/2008 à 15:13:03 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 14/10/2008 à 17:48:10
Avatar

Études : AFIP

Citation : jérémy_B
Code : PHP
1
2
3
4
5
6
<?php
$fld = new TextField('Url');
$fld->addValidator( new StringLengthValidator(0, 1500) );
$fld->addValidator( new RegexpValidator('#^http://([^/]+)(/.*)?$') ); // c'est un exemple ;)
$form->addField($fld);
?>


Très bon exemple jérémy, qui répond exactement à la question que je me posais dpuis le début, et grâce à a démarche que je viens de suivre je ne confondrais plus héritage avec utilisation ;)

Je te remercie grandement Tracker, je vais maintenant essayer d'élaborer une liste de validateurs utiles, dès qu'elle me semblera correcte je vous la communiquerais :D
Édité le 14/10/2008 à 17:49:34 par squall6969
 
Hors ligne Tracker # Posté le 14/10/2008 à 18:11:01
Avatar

Études : Université de Lyon

Allez, prévois 3 ou 4 validateurs avec noms et implémentations corrects, et on continue sur les Champs et les Formulaires enfin si tu es encore motivé...


Tracker.

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne Jérémy_B # Posté le 14/10/2008 à 20:17:16
Avatar

Merci Tracker pour ta réponse !

Si l'auteur du topic est d'accord, ainsi que toi Tracker, puis-je y participer en posant mes idées ou codes ?

Par exemple, Tracker, dans un de tes messages plus hauts, tu as lancé l'idée de classe nommée "StringLengthValidator".. Est-ce qu'elle pourrait avoir cette tête ? (c'est un complement de ce que tu avais mis) :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
class StringLengthValidator extends Validator{
	private $_max;
	private $_min;

	public function __construct($_max = 15, $_min = 3){
		$this->_max = $_max;
		$this->_min = $_min;
	}

	public function isValid($value){
		$l = strlen($value);
		return !( ($l>$this->_max) || ($l<$this->_min) );
	}
}
?>


Petite question : ceci retourne un booléen non ? --> return !( ($l>$this->_max) || ($l<$this->_min) ) C'est la première fois que je vois ça..!

En attendant de savoir si je peux participer, je vais réfléchir aux questions posées dans le dernier message par Tracker.
Édité le 14/10/2008 à 22:06:12 par Jérémy_B
Hors ligne Tracker # Posté le 14/10/2008 à 21:16:25
Avatar

Études : Université de Lyon

Oui ça pourrait ressembler à ça, quoi que:

private $l = 0;
private $value;
> ne servent à rien et que

_min et _max
> ne sont pas déclarés

et pour terminer
> isValid ne construit / ne stocke pas d'erreur (c'est ma faute cf code plus haut, mais c'est à modifier).

Et oui c'est un booléen :)


Tracker.
Édité le 14/10/2008 à 21:16:53 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne Jérémy_B # Posté le 14/10/2008 à 22:19:44
Avatar

Citation : Tracker
isValid ne construit / ne stocke pas d'erreur (c'est ma faute cf code plus haut, mais c'est à modifier).


Je comprend pas trop ce que tu veux dire par là.. Tu veux dire qu'avec mon code (que j'ai modifié), s'il y a une erreur, on peut rien retourner car il manque quelque chose dans isValid ? Un truc comme ceci :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class StringLengthValidator extends Validator{
	private $_max;
	private $_min;

	public function __construct($_max = 15, $_min = 3){
		$this->_max = $_max;
		$this->_min = $_min;
	}

	public function isValid($value){
		$l = strlen($value);

		if (!empty($l)){
			return !( ($l>$this->_max) || ($l<$this->_min) );
		}
		else{
			$this->error = 'La chaine est vide.';
			return false;
		}
	}
}
?>


Pourquoi on déclare pas $l et $value ? Tout attribut utilisé doit être déclaré non ?
Hors ligne Tracker # Posté le 14/10/2008 à 22:35:32
Avatar

Études : Université de Lyon

IsValid(...) à pour responsabilité (pour tous les types de validateur) de répondre vrai ou faux en réponse à la valeur soumise, mais classe doit également de conserver une trace des erreurs...:

Je change quelques noms de méthodes façon à rendre les choses plus claires. Le but étant de faire le plus de travail (générique) dans la classe mère limitant du coup le développement des classes filles:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
abstract class Validator
{
  private $_errors = array();

  public function isValid($value)
  {
    $this->_errors = array();
    $this->_analyse($value);
    return count($this->_errors)==0;
  }

  public function getErrors()
  {
    return $this->_errors;
  }

  abstract protected function _analyse($value);

  protected function _addError($message, array $arguments = array())
  {
    $this->_errors[] = array($message, $arguments);
  }
}

class StringLengthValidator extends Validator
{
  private $_max;
  private $_min;

  public function __construct($min = 3, $max = 15)
  {
    if ($max<$min) throw new Exception("Problème de définition du validateur");
    $this->_min = $min;
    $this->_max = $max;
  }

  protected function _analyse($value)
  {
    $l = strlen(''.$value);
    if($l<$this->_min) 
      $this->_addError('La chaine %s doit contenir plus de %d caractère(s)', array($value, $this->_min));
    if($l>$this->_max) 
      $this->_addError('La chaine %s doit contenir moins de %d caractère(s)', array($value, $this->_max));
  }
}


[ed]
L'utilisateur du validateur dispose donc des méthodes suivante pour interagir avec lui:
- isValid($value), qui répond oui/non
- getErrors(), qui retourne la liste des errors (dans un but d'affichage, peut-être multilingue, d'ou la séparation des valeurs et des chaines)

Un Validateur spécifique doit implémenter
- _analyse($value), qui a pour but de remonter les erreurs en utilisant sa méthode addErrors(...)


Citation : Jérémy_B
Pourquoi on déclare pas $l et $value ? Tout attribut utilisé doit être déclaré non ?

$l et $value, sont des variables locales pas des propriétés, i-e: elles n'existent que pendant de l'exécution de la fonction qui les définit.


Tracker.
Édité le 14/10/2008 à 23:08:24 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne Jérémy_B # Posté le 14/10/2008 à 23:12:58
Avatar

Mmmh.. pas mal ton code. Mais j'ai quelques petites questions :

1) return count($this->_errors)==0; --> retournera un booléen, je suppose que si c'est faux après avoir vérifié une valeur, tu feras une condition pour utiliser getErrors() et afficher les erreurs ?

2) $l = strlen(''.$value); --> Pourquoi tu fais une concaténation de $value avec du vide ?

3) isValid($value) est la méthode pour vérifier la valeur, elle passera par _analyse($value) pour faire des conditions.. J'ai du mal à voir comment tu vas procéder à l'instance de la class étant donné que le __construct() se trouve dans "StringLengthValidator", alors qu'on doit d'abord passer par isValid() dans "Validator"..! Est-ce comme ceci :

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
$chaine_a_tester = "Anticonstitutionnellement";

$a = new StringLengthValidator (0, 12);

if ($a->isValid($chaine_a_tester)) {
      // Affiche les erreurs car "count($this->_errors)==0" retourne true.
      echo $a->getErrors();
}
else {
      // Autre chose..!
}
?>


Bon, en espérant avoir compris ton code.
Édité le 14/10/2008 à 23:19:49 par Jérémy_B
Hors ligne Tracker # Posté le 14/10/2008 à 23:18:50
Avatar

Études : Université de Lyon

1) Oui
2) C'est l'équivalent d'un cast.
3) StringLengthValidator est aussi un Validator (héritage), donc
- toutes les méthodes public/protected de Validator sont dispo dans StringLengthValidator
- toutes les méthodes abstraites de Validator sont quand même invokable depuis les méthodes concrètes de Validator (_analyse depuis isValid par exemple), même si leurs implémentations appartiennent à une classe fille (et c'est là la puissance de l'abstraction).

Faut saisir les conséquences de l'héritage... ;)
> la même instance a les deux natures (polymorphisme) Validator et StringLengthValidator.


Le code suivant est suffisant:
Code : PHP
1
2
3
4
5
6
<?php
$v = new StringLengthValidator(3, 12);
if(!$v->isValid($ma_variable_a_valider))
{
  var_dump($v->getErrors());
}


[ed]
Pardon j'avais pas vu ton code (la loose), donc ok... (sauf que la condition c'est l'inverse).
Sinon ça commence à chauffer ?


Tracker.
Édité le 14/10/2008 à 23:41:01 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 14/10/2008 à 23:23:29
Avatar

Études : AFIP

Excellent, j'en apprend un rayon là !

Petite question, les "?>" sont omis volontairement à la fin des classes ?
parce que je sais que dans le framework de zend il y avait une histoire comme sa pour éviter du vide ou je sais pas trop quoi


Merci
 
Hors ligne Tracker # Posté le 14/10/2008 à 23:25:23
Avatar

Études : Université de Lyon

Si tu mets la balise de fermeture php ?> faudra faire gaffe qu'il n'y ait pas de caractère derrière type espace, sauts de ligne, etc... (sinon tu écris dans le flux de sortie et c'est chiant pour les headers).


Tracker.


>non c'est faux j'ai pas édité... :D
>Sinon suite demain, extinction pour moi ;) bye.
Édité le 15/10/2008 à 08:01:24 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 14/10/2008 à 23:32:32
Avatar

Études : AFIP

Ta réponse juste au dessus est très bien formulée :D
Donc le mieux c'est d'omettre les balises de fin

[Edit]
Voici mon avancement pour ce soir (je suis un peu mort)

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?php
abstract class Validator{
	
	private $_errors = array();

	public function isValid($value){
		$this->_errors = array();
		$this->_analyse($value);
		return count($this->_errors)==0;
	}

	public function getErrors(){
		return $this->_errors;
	}

	abstract protected function _analyse($value);

	protected function _addError($message,array $arguments = array()){
		$this->_errors[] = array($message, $arguments);
	}
}

class StringLengthValidator extends Validator{
	
	private $_max;
	private $_min;

	public function __construct($min = 3, $max = 15){
		if ($max<$min) throw new Exception("Problème de définition du validateur");
		$this->_min = $min;
		$this->_max = $max;
	}

	protected function _analyse($value){
		$l = strlen(''.$value);
		if($l<$this->_min) 
			$this->_addError('La chaine "'.$value.'" doit contenir plus de '.$this->_min.' caractère(s)', array($value, $this->_min));
		if($l>$this->_max) 
			$this->_addError('La chaine "'.$value.'" doit contenir moins de '.$this->_max.' caractère(s)', array($value, $this->_max));
	}
}

class StringRegexValidator extends Validator{
	
	protected $_regex;

	public function __construct($regex){
		$this->_regex = ''.$regex;
	}

	protected function _analyse($value){
		if(!preg_match($this->_regex,$value)) 
			$this->_addError('La chaine "'.$value.'" n\'est pas valide', array($value, $this->_regex));
	}
}

class MailStringRegexValidator extends StringRegexValidator{

	public function __construct(){
		$this->_regex = '#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#';
	}

	protected function _analyse($value){
		if(!preg_match($this->_regex,$value)) 
			$this->_addError('Le mail "'.$value.'" n\'est pas valide', array($value));
	}
}

//le test pour le mail pour exemple

$ma_variable_a_valider="adressehotmail.com";
$v = new MailStringRegexValidator();
if(!$v->isValid($ma_variable_a_valider)){
	$Err = $v->getErrors();
	//print_r($Err);
	foreach($Err as $key=>$e){
		echo $e[$key];
	}
}


Petites questions:
-les arguments passés à la fonction _addError sont simplement là pour le débugage non? De même que l'utilisation du var_dump qui renvoi le tout structuré.

- Dans la classe mère, pourquoi caster "array $arguments = array()", cela optimise t'il le code, ou est-ce pour encapsuler ?

-est-ce que ce que j'ai fais jusqu'à présent est correcte ?


Merci :)
Édité le 15/10/2008 à 01:29:33 par squall6969
 
Hors ligne Jeremie64 # Posté le 15/10/2008 à 01:59:31
Get over it !
Avatar

Vraiment, ce bon vieux Tracker en aide plus d'un ;)

Je sais pas ce qu'on ferait sans lui ^^

Coding is more than a job, more than hobby, more than activity, it's a lifestyle !

PHP is a powerful programming language, if you know how to use it...



 
Hors ligne squall6969 # Posté le 15/10/2008 à 02:07:31
Avatar

Études : AFIP

Voici un nouveau début, largement inspiré de ce qui précède.

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
abstract class BddConnector{

	private $_errors = array();
	
	public function isConnected($hostname , $utilisateur , $pass="" ){
		$this->_errors = array();
		$this->_connection($hostname , $utilisateur , $pass="" );
		return count($this->_errors)==0;
	}

	public function getErrors(){
		return $this->_errors;
	}

	abstract protected function _connection($hostname , $utilisateur , $pass="" );

	protected function _addError($message,array $arguments = array()){
		$this->_errors[] = array($message, $arguments);
	}

}

class MysqlBddConnector extends BddConnector{

	
	protected function _connection($hostname , $utilisateur , $pass="" ){
			if(!@mysql_connect($hostname , $utilisateur , $pass))
				$this->_addError('La connexion à la base de donnée Mysql "'.$hostname.'" a échoué.', array($hostname , $utilisateur , $pass));
	}
}


//test de connexion
$hostname="locaflhost";
$utilisateur="root";
$pass="";

$v = new MysqlBddConnector();

if(!$v->isConnected($hostname , $utilisateur , $pass)){
	$Err = $v->getErrors();
	print_r($Err);
	foreach($Err as $key=>$e){
		echo $e[$key];
	}
}


Sa sera tout pour aujourd'hui, demain si tout est ok j'enchaîne sur la selection de la base de donnée

j'espère que j'ai bien compris le principe :)
 
Hors ligne Tracker # Posté le 15/10/2008 à 08:33:52
Avatar

Études : Université de Lyon

@squall6969:
Citation
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
class MailStringRegexValidator extends StringRegexValidator{

	public function __construct(){
		$this->_regex = '#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#';
	}

	protected function _analyse($value){
		if(!preg_match($this->_regex,$value)) 
			$this->_addError('Le mail "'.$value.'" n\'est pas valide', array($value));
	}
}


1/ Change le nom MailValidator suffira (l'utilisateur s'en tape de savoir qu'à l'intérieur y'a une regex). Idem pour StringRegexValidator -> RegexValidator

2/ Tu as un problème d'appel du constructeur parent, on devrait trouver:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class MailValidator extends RegexValidator
{
  public function __construct()
  {
    parent::__construct('#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#');
  }
  
  // Et pas forcement besoin de surcharger _analyse elle existe déjà dans RegexValidator
  // La surcharge peut être faite pour donner des précisions sur l'erreur:

  protected function _analyse($value)
  {
    parent::_analyse($value);
    if($this->hasError())
      $this->_addError('La chaine attendue doit avoir le format d\'un email {votre identifiant}@{nom de domaine}');
  }

  // si tu optes pour cette possibilité, je te laisse ajouter la méthode 
  // hasError() à l'endroit qu'il te parait convenir... attention  :) 
}


Sinon pour ta connexion SQL. C'est tentant de recopier de suite ce que tu as compris mais:
1/ Est-ce pratique de se connecter en appelant une méthode isConnected ?
2/ L'échec de connexion n'est pas une erreur utilisateur, c'est une exception.
3/ Pourquoi une connexion contiendrait une liste d'erreurs ?
4/ Si on a deux instances de connexion, ne devrait-elle pas refléter deux connexion physique différentes au sgbd ?
5/ etc...

On utilise pas une voiture comme un lave-vaisselle, de la même façon un Validateur a une "logique d'interaction" différente d'une connexion à un sgbd. Sinon y'a, à priori, aucune boulette syntaxique dans ton code.

C'est là qu'on commence à voir les différents niveaux de compréhension de l'OO. Avec un code syntaxiquement correct, on peut aboutir à un ensemble:
level 0 - Totalement non objet. (Production du gars qui n'a rien capté, peut-être V.... ?)
level 1 - inutile (complètement attaché au besoin > manque d'objets > pas réutilisable)
level 2 - pas pratique (les responsabilités de chaque objet sont mal distribuées > pas réutilisable)
level 3 - utilisable (mais y'a matière à simplifier)
level 4 - parfait ou presque ;)


Pour ta connexion, définis le système (les entités [objets de types différents intervenant], et les rôles de chacun).


Tracker.
Édité le 15/10/2008 à 11:14:33 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 15/10/2008 à 11:19:31
Avatar

Études : AFIP

Voilà, j'ai essayé d'apporter les modifications nécessaires à ma classe Validator et ses classes héritantes. :)

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
abstract class Validator{
	
	private $_errors = array();

	public function isValid($value){
		$this->_errors = array();
		$this->_analyse($value);
		return count($this->_errors)==0;
	}

	public function getErrors(){
		return $this->_errors;
	}

	abstract protected function _analyse($value);

	protected function _addError($message,array $arguments = array()){
		$this->_errors[] = array($message, $arguments);
	}
	
	//renvoi 1 en cas d'erreur et 0 s'il n'y a pas d'erreurs
	public function hasError(){
		return count($this->_errors)!=0;
	}
}

class StringLengthValidator extends Validator{
	
	private $_max;
	private $_min;

	public function __construct($min = 3, $max = 15){
		if ($max<$min) throw new Exception("Problème de définition du validateur");
		$this->_min = $min;
		$this->_max = $max;
	}

	protected function _analyse($value){
		$l = strlen(''.$value);
		if($l<$this->_min) 
			$this->_addError('La chaine "'.$value.'" doit contenir plus de '.$this->_min.' caractère(s)', array($value, $this->_min));
		if($l>$this->_max) 
			$this->_addError('La chaine "'.$value.'" doit contenir moins de '.$this->_max.' caractère(s)', array($value, $this->_max));
	}
}

class RegexValidator extends Validator{
	
	protected $_regex;

	public function __construct($regex){
		$this->_regex = ''.$regex;
	}

	protected function _analyse($value){
		if(!preg_match($this->_regex,$value)) 
			$this->_addError('La chaine "'.$value.'" n\'est pas valide', array($value, $this->_regex));
	}
}

class MailValidator extends RegexValidator{

	public function __construct(){
		parent::__construct('#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#');
	}

	protected function _analyse($value){
		parent::_analyse($value);
		if($this->hasError())
			$this->_addError('Le mail "'.$value.'" n\'est pas valide', array($value));
	}
}


En ce qui concerne ma connexion SQL, étant donnée qu'effectivement

Citation : Tracker
On utilise pas une voiture comme un lave-vaisselle :D


je vais retravailler le tout dans la journée.

Petite question pour m'orienter:
-faut t'il que je crée une variable de type array me permettant de stocker les connexions en cours?
pour répondre à
Citation : Tracker
4/ Si on a deux instances de connexion, ne devrait-elle pas refléter deux connexion physique différentes au sgbd ?


Sinon pour
Citation : Tracker
1/ Est-ce pratique de se connecter en appelant une méthode isConnected ?

j'avoue que moi même sa me perturbait, et je vais donc y réflechir pour trouver quelque chose de plus cohérent. :)


Après:
Citation : Tracker
2/ L'échec de connexion n'est pas une erreur utilisateur, c'est une exception.

A l'heure actuelle je ne vois pas bien la différence entre exception et erreur utilisateur.(l'exception, c'est finalement une erreur prédéfinie par Php, alors si on veut suivre la logique POO, il faut les utiliser dès que possible ![c'est sa ? :o ])

Et pour finirCitation : Tracker
3/ Pourquoi une connexion contiendrait une liste d'erreurs ?

En fait là encore si je comprends bien, vu que dans ce cas, les erreures lèvent des exceptions php, il est inutile de faire une liste d'erreur et il suffirait tout simplement de créer un booléen qui renverrait l'état de la connexion ?

Une fois que j'aurais un peu plus d'info sur les derniers éléments de la connexion sql, j'essayerais de Citation : Tracker
Définir le système (les entités [objets de types différents intervenant], et les rôles de chacun).


Encore une fois, ce Post est génial et risque d'aider beaucoups de gens :D

Merci Tracker :ange:

[Edit]
J'ai essayé d'avancer un peu sur la connexion sql

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
abstract class BddConnector{

	private $_error;
	private $_connexion=array();
	
	public function Connection($hostname , $utilisateur , $pass="" ){
		$this->_error = 0;
		$this->_connect($hostname , $utilisateur , $pass="" );
		return $this->_error;
	}
	
	protected function _setError(){
		$this->_error = 1;
	}
	
	public function getError(){
		return $this->_error;
	}

	abstract protected function _connect($hostname , $utilisateur , $pass="" );

	protected function _setConnexion(array $connexion=array()){
		$this->_connexion = $connexion;
	}
	
	

}

class MysqlBddConnector extends BddConnector{

	//Je ne suis pas du tout sure de la syntaxe au niveau de cette méthode
	protected function _connect($hostname , $utilisateur , $pass="" ){
			$c[]=@mysql_connect($hostname , $utilisateur , $pass);
			if(!$c) throw new Exception("Paramètres de connexion invalide.");
				$this->_setError();
			else{
				$this->_setConnexion($c);
			}
	}
}


Est_ce que cela correspond mieux ?
Édité le 15/10/2008 à 11:42:48 par squall6969
 
Hors ligne Tracker # Posté le 15/10/2008 à 11:54:03
Avatar

Études : Université de Lyon

Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Tu n'as pas fait attention mais:
Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?php
class MailValidator extends Validator
{
  //...
  protected function _analyse($value)
  {
    parent::_analyse($value);
    if($this->hasError())
      $this->_addError('Le mail "'.$value.'" n\'est pas valide', array($value));
  }
  // ...
}


1/ D'abord félicitations hasError() ne pourrait pas être mieux placée.
2/ Par contre si tu as une erreur de validation de Mail, tu vas avoir comme erreur:
$arr[0] = 'La chaine "'.$value.'" n\'est pas valide' ...
$arr[1] = 'Le mail "'.$value.'" n\'est pas valide' ...

Ce qui est plutôt redondant, l'idée étant d'apporter une information complémentaire dans ce cas, comme le format attendu.


Citation
[...] faut t'il que je crée une variable de type array me permettant de stocker les connexions en cours?

Si tu voulais créer un annuaire de connexion oui, encore que tu ferais un tableau d'objets connexion, mais pour l'instant,
> une instance de ta classe connexion == une connexion physique ouverte, ou
> deux instances == deux connexion différentes ouvertes.
ps: quel serait l'intérêt de disposer d'une connexion fermée ?


Citation
[...] je ne vois pas bien la différence entre exception et erreur utilisateur.

Une exception c'est un incident que ton traitement courant ne peut pas prendre en compte, donc il sort de son cours normal en envoyant un message (objet exception) à toutes les méthodes de la pile d'appel dans l'espoir de trouver un block try {} catch() {} plus haut susceptible de traiter l'incident. Au plus haut niveau, l'utilisateur devrait être prévenu d'une impossibilité temporaire de traitement.

Sinon pour ta connexion, vu de loin, des "Requêtes" fabriquent des "Résultats" s'il n'y a pas d'erreur...


[ed] pour ta classe SQL, saute pas sur l'implémentation, réfléchis aux intervenants qui composent le système d'abord et comment ils s'articulent. Après vu avec l'oeil d'un utilisateur de tes classes, comment penses-tu interagir avec ?


Tracker.
Édité le 15/10/2008 à 12:05:42 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 15/10/2008 à 12:09:11
Avatar

Études : AFIP

Citation : Tracker
$arr[0] = 'La chaine "'.$value.'" n\'est pas valide' ...
$arr[1] = 'Le mail "'.$value.'" n\'est pas valide' ...

Ce qui est plutôt redondant, l'idée étant d'apporter une information complémentaire dans ce cas, comme le format attendu.


Donc en fait je remplace tout simplement le message d'erreur par quelque chose de bien plus précis, en l'occurrence : Le format attendu est un mail

Pour ce qui est de tes pistes pour la suite, je dois reprendre ma classe rajouté dans mon dernier post pour créer une instance par connexion.

et pour finir, je suis d'accord que Citation : Tracker
Sinon pour ta connexion, vu de loin, des "Requêtes" fabriquent des "Résultats" s'il n'y a pas d'erreur...
 
Hors ligne Tracker # Posté le 15/10/2008 à 12:24:03
Avatar

Études : Université de Lyon

[ed] pour ta classe SQL, saute pas sur l'implémentation, réfléchis aux intervenants qui composent le système d'abord et comment ils s'articulent. Après vu avec l'oeil d'un utilisateur de tes classes, comment penses-tu interagir avec ?

Schématise avant toute chose, sinon tu vas te perdre dans les détails d'implémentation et finalement pas avancer...

L'analyse se fait du plus gros au plus précis, la phrase précédente:
Citation
Sinon pour ta connexion, vu de loin, des "Requêtes" fabriquent des "Résultats" s'il n'y a pas d'erreur...

te permet déjà de faire sortir du bois deux entités Requêtes et Résultats, autres que Connexion, mais comment le système peut bien être foutu ?


Tracker.

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 
Hors ligne squall6969 # Posté le 15/10/2008 à 13:08:59
Avatar

Études : AFIP

Je penses voir ou tu veux en venir,

En utilisant requêtes et résultats on prépare la classe à exécuter des requêtes sql et à récupérer les résultats.


Citation : Tracker
les entités [objets de types différents intervenant], et les rôles de chacun

En fait depuis le début tu me proposes de définir les rôles et les objets de types différents intervenant, déjà je ne suis pas sure de comprendre "les objets de types différents intervenant",
-est-ce que ce sont les instance extérieures éventuels nécessaire (donc les dépendances)?
-ou est-ce que c'est le listing des paramètres de chaque objet qui va hérité de a classe mère.

Je n'ai jamais encore créer de structure théorique avant de coder, puisque mes notions en POO étaient trop faibles, et c'est l'occasion ou jamais:

Code : Console
hiérarchie:
-SQL
     -SqlConnector
     =>permettre de faire une connexion sql
           -MysqlConnector
           =>permettre de faire une connexion sql à une bdd mysql
                -MysqlDbConnector
                => sélectionner une Bdd
                     -RequeteSQL
                     =>exécuter des requêtes sql
                          -ResultatSQL
                          =>renvoyer les résultats d'un requête


SQL étant une classe abstraite avec 3 méthodes abstraites:
1/-connect($hostname , $utilisateur , $pass="") => connexion à la base de donnée
2/-execRequete($sql) => exécution d'une requête sql
3/-resultatRequete() => Retourne les résultats

J'aurais pu aller plus loin, par exemple en fournissant différent types de résultats attendu par exemple tableau associatif ou numérique, mais auparavant j'aimerais savoir si m'a démarche de conception est bonne.

MERCI :)
Édité le 15/10/2008 à 13:10:32 par squall6969
 
Hors ligne Tracker # Posté le 15/10/2008 à 13:24:58
Avatar

Études : Université de Lyon

Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Pas exactement, si tu reprends les termes:
Qu'est-ce qu'une Requête ?
  • une chaine, des variables...
  • une Méthode Execute ?


Qu'est-ce qu'un Résultat ?
- Ce qui sort de la méthode Requête:Exécute
Alors suivant les cas:
  • une erreur ?
  • une valeur d'auto incrément
  • un statut d'exécution
  • une ressource parcourable (pour fetch())


Niveau utilisation les choses se profilent:

Code : PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$cnx = new MysqlConnexion(...);
$qry = $cnx->prepareQuery('insert toto values (null, :name)');

$rst = $qry->execute(array('name'=>'Tracker:)'));
if($rst->isSuccess())
{
  echo $rst->getLastId();
  // ...
}
else
{
  throw new Exception($rst->getError());
}


// ou encore:
$cnx = new MysqlConnexion(...);
$qry = $cnx->prepareQuery('select * from toto where name = :name');
foreach($qry->execute(array('name'=>'Tracker:)')) as $row)
  var_dump($row);

//...



Je vois bien que tu cherches à abstraire la bdd (rendre tes méthodes indépendantes de la base et donc du driver correspondant), mais dans un premier temps concentre toi sur l'essentiel, on fera ça dans un second temps.


Tracker.
Édité le 15/10/2008 à 13:47:14 par Tracker

Un peu de lecture: PHP // MySQL // JavaScript // SQL
Cherche Job en télétravail ou près de Lorient (56)
 

Retour au forum "PHP" ou à la liste des forums

Pour accéder à cette section
Connectez-vous !
connexion_rpx