[PHP5] OBSERVER DESIGN PATTERN

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 - 17 juil. 2007 à 07:18
FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 - 10 août 2007 à 17:10
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/43478-php5-observer-design-pattern

FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 3
10 août 2007 à 17:10
Bon, j'ai fais un truc avec les observateurs et les évenements coté serveur... mais n'ayant plus internet jusqu'à la mi septembre, je ne peux pas poster le code avant.

Mais dès que je peux , je t'en fais profiter Mala :)

a++
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
22 juil. 2007 à 14:40
Hello,

1 - exact, curieux que cela fonctionne d'ailleurs (vu que ceci est une copie de mon code).

2 - c'est intentionnel. Que l'ojet existe déjà ou pas, dans tous les cas, c'est ok. Le seu problème serait qu'on attache pas un SplObservern ce qui provoquera une erreur fatale de toute façon puisque je le force dans l'appel dans la méthode.
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
20 juil. 2007 à 18:08
# public function attach(SplObserver $observer) {
# if(!$this->aObservers->contains($observer)) {
# $this->aObservers->attach($observer);
# }
# return true;
# }
cette fonction va retourner 'true' dans tous les cas.
le return true doit etre dans le bloc if(){} et false en dehors
amezghal Messages postés 385 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 21 août 2015 5
20 juil. 2007 à 17:57
ya une ptite erreur
deux public
# public public function next() {
# next($this->storage);
# $this->index++;
# }
FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 3
18 juil. 2007 à 17:52
mon exemple plus haut ne marche pas... je corrige ca au plus vite :)
FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 3
18 juil. 2007 à 14:27
J'ai oublié de mettre une méthode pour changer le "state" à la fin de ma recherche d'évènement sur mes observers.
On peut éventuellement rajouter un flag pour garder le dernier changement d'état :

abstract class Item {
proteted $lastState;
protected function KillState() {
$this->lastState = $this->state;
unset($this->state);
}
}

class Visitor extends Item {
public function AuthValidation() {
// code
$this->SeekForEvent();
$this->KillState();
}
}

Voila voila :)
FhX Messages postés 2350 Date d'inscription mercredi 13 octobre 2004 Statut Membre Dernière intervention 18 avril 2015 3
18 juil. 2007 à 00:52
Ah ca j'adore :)
Le mieux en utilisant les observers, c'est d'utiliser un état (state).

En pratique, voila ce que ca peut donner. On va compter le nombre de logging d'un utilisateur. Si le nombre est de 3, on annule toute possibilité d'identification.
Si par contre, le login et le mot de passe sont bon, alors on redirige.

J'ai mis 2 modules ici, le premier est le comptage du nombre de logging.
Le second est le module de redirection en fonction du "state" de l'objet.
Je n'ai pas mis d'interfaces, c'est juste du vite fait :

<?php
abstract class Item {

protected $_mods = null;
protected $state = null;

public function __construct() {

}

final protected function getState() {
return $this->state;
}
final protected function setState($state) {
$this->state = $state;
}
final protected function ModExist( Module $mod ) {
foreach ( $this->_mods as $obj)
if ( $object === $obj )
return true;
return false;
}

final public function AddMod( Module $mod ) {
if ( !$this->contains($mod) )
$this->$_mods[] = $mod;
}

final public function DeleteMod( Module $mod ) {
foreach ( $this->_mods as $i => $obj) {
if ( $mod === $obj ) {
unset( $this->_mods[$idx] );
return;
}
}
}

final public function SeekForEvent() {
foreach ( $this->_mods as $mod)
$mod->SeekEvent($this);
}
}

class Visitor extends Item {

const __WRONG_AUTHENTIFICATION__ = 'wrong_login_auth';
const __SUCCESSFUL_AUTHENTIFICATION__ = 'right_login_auth';

const __MAX_ATTEMPT_FOR_LOGIN__ = 'wrong_login_count';

private $login;
private $password;


public function setLogin($login) {
$this->login = trim($login);
}
public function getLogin() {
return $this->login;
}
public function setPassword($password) {
$this->password = trim($password);
}
public function getPassword($hashed=true) {
return $hashed ? sha1($this->password) : $this->password;
}

public function AuthValidation() {
if ( $this->getState() === self::__MAX_ATTEMPT_FOR_LOGIN__ )
throw new LoginException();

$data $mysqli->query('SELECT COUNT(*) FROM .... WHERE login "..." AND password = "..." ')->fetch_row();
if ( (int) $data[0] === 1 )
$this->setState(self::__SUCCESSFUL_AUTHENTIFICATION__);
else
$this->setState(self::__WRONG_AUTHENTIFICATION__);

$this->SeekForEvent();
}

}

class AttempLogin {

private $maxLoginAttemp = 3;
private $CurrentLoginAttemp = 0;

public function SeekEvent( Item $item ) {
switch ( $item->getState() ) {
case Visitor::__WRONG_AUTHENTIFICATION__ :
$this->CurrentLoginAttemp++;
if ( $this->CurrentLoginAttemp >= $this->maxLoginAttemp ) {
$item->setState(Visitor::__MAX_ATTEMPT_FOR_LOGIN__);
throw new LoginException();
}
break;
}

}

}
class Redirect {

public function SeekEvent( Item $item ) {
switch ( $item->getState() ) {
case Visitor::__SUCCESSFUL_AUTHENTIFICATION__ :
header('Location: ./membre.php');
exit();
break;
}
}

}

if ( isset($_SESSION['user']) && $_SESSION['user'] instanceof Visitor ) {
$user = $_SESSION['user'];
} else {
$user = new Visitor;
$user->AddMod( new AttempLogin );
$user->AddMod( new Redirect );
}

$user->setLogin('login de test');
$user->setPassword('Mot de passe de test');

try {
$user->AuthValidation();
} catch ( LoginException $e ) {
echo $e->getMessage();
$_SESSION['user'] = $user;
}

?>

Voila ce que ca peut donner plus ou moins :)
A travailler bien sur ^^

Je ne met pas ca en tant que code pour éviter la concurrence et la duplication de sources, mais je le met ici pour donner un exemple plus concret :)

Vala !
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
17 juil. 2007 à 09:06
Dans un contrôle radar, c'est bien le radar qui observe la voiture.
De plus, on peut très bien voir les observateurs comme des modules greffés à la voiture, dans ce cas.
Toujours est il que c'est ujn principe qui fonctionne bien, et colle bien à la POO je trouve.
A la base, mon exemple prenait des commandes qui étaient traitées, puis expédiées, avec envoi d'email au destinataire, etc...mais bon, la voiture c'était pour rester dans la même analogie que la source précédente de localstone ;-)
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
17 juil. 2007 à 07:18
c'est etrange comme source, mais pourquoi pas :)

coder un radar :) je trouve ca etrange que ca soit autre chose qui observe l'objet, alors que l'objet possede lui meme du code pour qu'on lui branche quelquechose...
Rejoignez-nous