getter / setter

Geeze
Invité n'ayant pas de compte PHPfrance

04 juin 2010, 17:06

Bonjour à vous.

Je dois réaliser une application PHP ou je dois pouvoir créer des pays.

J'ai lu aujourd'hui la possibilité de faire des __get et __set, ça m'a l'air vraiment bien (plus propre que faire un get/set pour chaque paramètre, à mon avis) mais il y a un problème qui a sûrement dû être résolu et que je n'arrive pas à résoudre.

Voici mon code (la question suivra):
class Pays {

    private $parametres = array();

    public function __construct($nomRecu) {
        $this->parametres[nom] = $nomRecu;
    }

    public function __set($parametreRecu, $valeurRecue) {
        $this->parametres[$parametreRecu] = $valeurRecue;
    }

    public function __get($parametreRecu) {
        return $this->parametres[$parametreRecu];
    }
    
    public function  __toString() {
        $retour = 'Nom du pays: '.$this->parametres[nom];
        return $retour;
    }
  }
Voilà, donc tout ça c'est bien joli.. Mais moi je souhaite avoir uniquement le paramètre "nom" dans ma classe pays.. Et là il y a un problème je crois: si un gogol me fait: le code suivant...
$lePays = new Pays(Suisse);
$lePays->population = 7000000;
... et bien il m'aura créé un nouveau paramètre "population".. Ou je me trompe? Bref, comment limiter les paramètres uniquement à "nom", tout en gardant ma structure de code? Ou comment faire un code plus propre?

Merci d'avance :-)

Eléphant du PHP | 86 Messages

04 juin 2010, 17:20

A quoi te servent tes get et set si tu n'as besoin que d'un paramètre ... ?
Mieux encore, à quoi sert le tableau ? Une simple variable $nom suffirait...

Modérateur PHPfrance
Modérateur PHPfrance | 6037 Messages

04 juin 2010, 17:27

Modération :
Merci d'utiliser un titre clair et qui correspond bien à ta demande.

Merci de prendre le temps de lire les règlements.
Règle n°2 du webmaster : Toujours commencer par le HTML qu'on veut obtenir....toujours ! :priere:
J'aime apprendre de nouvelles choses.

Geeze
Invité n'ayant pas de compte PHPfrance

04 juin 2010, 17:41

Mon projet contiendra, tu l'imagines bien, plus d'une classe qui ont plus qu'un paramètre (hormis celle-là, qui est l'exception).

Je tiens donc à garder la même structure pour chacune de mes classes, au risque de me retrouver avec ce genre d'incohérences:
$unClient = new Client('Eddie', 'Vedder', 'Musicien');
echo $unClient->nom;

$unPays = new Pays('Suisse');
echo $unPays->getNom();
Donc j'ai fait un tableau, même pour un seul paramètre, pour pouvoir utiliser les méthodes magiques __set et __get ... Il y a un autre moyen?

PS: Désolé pour le titre foireux, fausse manipulation..

Geeze
Invité n'ayant pas de compte PHPfrance

05 juin 2010, 11:31

Merci à la communauté pour, à défaut de m'avoir aidé à résoudre mon problème, m'avoir gentiment fait remarqué que je m'étais planté dans le titre et pour avoir critiqué mon code de manière
non constructive, sans proposer de solution.

Ça vaut la peine de prendre le temps d'écrire un message explicite et courtois, tiens.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

05 juin 2010, 14:20

Il est vrai qu'il suffit d'un message explicite et courtois pour que toute une communauté s'émeuve, abandonne tout ce qu'elle pouvait être en train de faire pour te consacrer tout son temps et t'apporter une solution dans l'heure... personnellement je n'en suis pas convaincu... en revanche, pense que l'ironie, le manque de courtoisie ou l'impatience ne l'y inciteront certainement pas.

Ceci étant, pour répondre à tes questions, effectivement, si tu implémentes la méthode __set() et que tu utilises un tableau pour stocker tous les attributs de ta classe, le développeur pour effectivement ajouter des attributs dans son instance.

En gros, ta classe ne change pas, en revanche tu permets au développeur d'ajouter des attributs à la volée, attributs qui ne lui serviront à rien, puisque tout ce qu'il pourra faire avec c'est venir les lire avec __get().

Si tu ne veux pas que le développeur puisse bricoler les instances de ta classe, il te faut déclarer chacun des attributs individuellement (d'où la remarque de Skikit). Et en ce qui me concerne, je préfère générer un getter et un setter pour chaque attribut. C'est plus long, mais je peux ainsi contrôler les valeurs qu'ils essayeraient de saisir (interdire une chaine quand j'attend un nombre, limiter la taille d'une chaine, le format d'une date, etc.)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Geeze
Invité n'ayant pas de compte PHPfrance

06 juin 2010, 13:55

Merci pour ta réponse Ryle, il est vrai que je ne reproche rien à la communauté mais plutôt aux personnes qui viennent juste critiquer sans apporter de réelle aide.

C'est vrai que d'avoir un getter et un getter pour chacun dans attributs est pratique pour contrôler les valeurs saisies.. Mais dans mon cas, ce contrôle se fait plus tard dans la classe qui s'occupe d'interagir avec la base de données (services CRUD) sur la base de données, donc je ne vais pas faire de double contrôle.

J'ai finalement opté pour l'ajout d'une petite méthode afin d'éviter qu'un type vienne m'ajouter une date dans ma Personne:
public function verifierParametre($tousLesParametres, $parametreAVerifier) {
            $parametreValide = false;
            // Parcourt les paramètres de la classe
            foreach ($tousLesParametres as $parametre=>$contenu) {
                // Vérifie si un paramètre correspond au paramètre reçu
                if ($parametre == $parametreAVerifier)
                    $parametreValide = true;
            }
            // Si le paramètre n'est pas valide, afficher l'erreur
            if (!$parametreValide)
                echo 'Erreur: paramètre *'.$parametreAVerifier.'* inexistant.<br>';
            return $parametreValide;
}
Les avantages que je trouve sont: moins de code à écrire / plus de lisibilité lorsque l'ont veut interagir avec la classe
Les inconvénients que je trouve sont: exécution plus lente du code / pas de contrôle direct des valeurs saisies

J'opte finalement pour cette solution, s'il y a un inconvénient majeur que je n'ai pas relevé et qui pourrait vraiment décrédibiliser cette solution, merci de me le faire savoir!

Une autre question que je me pose (je n'ai pas trouvé de réponse) est la suivante: l'idéal serait de déclarer uniquement les entrées de mon tableau associatif mais sans leur donner de valeurs.. Je sais pas si c'est possible de faire ça? Ca éviterait le problème de lenteur d'exécution car je n'aurais pas besoin d'appeler la fonction ci-dessus.

Mammouth du PHP | 568 Messages

07 juin 2010, 09:49

Sinon tu peux aussi vérifier que la variable éxiste bien dans ta class;
//magic setter
		protected function __set($key, $value) {
			if(isset($this->$key)) {
				$this->$key = $value;
			} else {
				throw new Exception('Unknow attribute '.$key);
			}
		}
		
		//magic getter
		protected function __get($key) {
			if(isset($this->$key)) {
				return $this->$key;
			} else {
				throw new Exception('Unknow attribute '.$key);
			}
		}

Geeze
Invité n'ayant pas de compte PHPfrance

07 juin 2010, 11:12

Wow.. C'est pas plus dur que ça, tiens..

Merci beaucoup Yosh, ta méthode m'a l'air plus simple!