Ver Mensaje Individual
  #9 (permalink)  
Antiguo 21/03/2008, 14:27
Avatar de pragone
pragone
 
Fecha de Ingreso: diciembre-2007
Ubicación: Madrid
Mensajes: 223
Antigüedad: 16 años, 5 meses
Puntos: 2
Re: Opiniones sobre el patrón de Invocación Implicita

Ok... ya tengo un prototipo funcionando.

Para esto he utilizado aquel framework de ActiveRecord que había creado "PHP5DbObject".

El ejemplo que he utilizado: Un torneo (uno muy corto).

En mi BD he creado tres tablas:
Código PHP:
desc cup;
+--------+--------------+------+-----+---------+----------------+
Field  Type         Null Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
id     int(11)      | NO   PRI NULL    auto_increment |
name   varchar(255) | NO   |     |         |                |
winner int(11)      | YES  |     | NULL    |                |
+--------+--------------+------+-----+---------+----------------+

desc game;
+------------+--------------+------+-----+---------+----------------+
Field      Type         Null Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
id         int(11)      | NO   PRI NULL    auto_increment |
cup_id     int(11)      | NO   |     |         |                |
play_date  datetime     YES  |     | NULL    |                |
team_home  int(11)      | YES  |     | NULL    |                |
team_visit int(11)      | YES  |     | NULL    |                |
winner     int(11)      | YES  |     | NULL    |                |
result     varchar(255) | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

desc listen;  // Utilizada por el Messenger
+------------+--------------+------+-----+---------+----------------+
Field      Type         Null Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
id         int(11)      | NO   PRI NULL    auto_increment |
event_name varchar(255) | NO   |     |         |                |
source     varchar(255) | NO   |     |         |                |
interested varchar(255) | NO   |     |         |                |
params     text         NO   |     |         |                |
+------------+--------------+------+-----+---------+----------------+ 
Luego he creado este par de clases: Cup y Game... cada una extiende de la clase de acceso a DB que PHP5DBObject crea CupDB y GameDB respectivamente.

Código PHP:

class Game extends GameDB {
    public function 
setHomeAsWinnerOf(&$game) {
        
Messenger::getInstance()->interestedIn('WinnerOfGame'$game$this, array('setas' => 'home'));
    }
    
    public function 
setVisitorAsWinnerOf(&$game) {
        
Messenger::getInstance()->interestedIn('WinnerOfGame'$game$this, array('setas' => 'visitor'));
    }
    
    public function 
setWinnerAs($team) {
        if (
$team == 'home'$this->winner $this->team_home;
        else 
$this->winner $this->team_visit;
        print 
"<hr><strong>The $team team won game " $this->id "!!</strong>";
        
$this->update();
        
Messenger::getInstance()->notify('WinnerOfGame'$this);
        
Messenger::getInstance()->notify('LooserOfGame'$this);
    }
    
    public function 
setHomeTeam($team) {
        print 
"Now the home team of game " $this->id " is " $team "<br>";
        
$this->team_home $team;
        
$this->update();
    }
    
    public function 
setVisitorTeam($team) {
        print 
"Now the visitor team of game " $this->id " is " $team "<br>";
        
$this->team_visitor $team;
        
$this->update();
    }
    
    public function 
listener($event, &$source$params = array()) {
        switch(
$event) {
            case 
'WinnerOfGame':
                print 
"Game id: " $this->id " is being notified of a winner.<br>";
                print 
"It's the result of game: " $source->id " and it's team " $source->getWinner() . "<br>";
                print 
"Params : <pre>" print_r($paramstrue) . "</pre>";
                if (
$params['setas'] == 'home'$this->setHomeTeam($source->winner);
                else 
$this->setVisitorTeam($source->winner);
        }
    }
}


class 
Cup extends CupDB {
    public function 
setFinal(&$game) {
        
Messenger::getInstance()->interestedIn('WinnerOfGame'$game$this, array(''));
    }
    
    public function 
listener($event, &$source$params = array()) {
        switch(
$event) {
            case 
'WinnerOfGame':
                print 
"Cup id: " $this->id " is being notified of a winner.<br>";
                print 
"It's the result of game: " $source->id " and it's team " $source->getWinner() . "<br>";
                print 
"Params : <pre>" print_r($paramstrue) . "</pre><br>";
                
$this->winner $source->winner;
                print 
"<H1>Congratulations team " $this->winner ". Yuo Won the <em>" $this->name "</em></h1>";
                
$this->update();
        }
    }

Y finalmente mi clase Messenger. Esta clase aprovecha las bondades de PHP5DBObject para cargar la instancia del objeto que debe ser notificado con el método PHP5DBObject::factory($class_name, $id);

Código PHP:

class Messenger {
    protected static 
$instance null;
    
    public static function &
getInstance() {
        if (!
is_object(self::$instance)) {
            
self::$instance = new Messenger();
        }
        return 
self::$instance;
    }
    
    function 
__construct() {
        if (
is_object(self::$instance)) throw new Exception(__CLASS__ ' is singleton. You shouldn\'t call it directly but using the static method ' __CLASS__ '::getInstance()');
    }
    
    function 
notify($event_name, &$source) {
        print 
"<hr>";
        print 
"Notifying of event $event_name by " get_class($source) . '@' http_build_query($source->getArrayId()) . "<br>";
        
$listeners Listen::browse('event_name=? AND source=?', array($event_nameget_class($source) . '@' http_build_query($source->getArrayId())));
        if (
count($listeners) == 0) {
            print 
"Who cares...  :P <br>";
            return;
        }
        foreach(
$listeners as $listener) {
            list(
$class$id) = split('@'$listener->interested2);
            
parse_str($listener->params$params);
            
parse_str($id$array_id);
            
$null null;
            
$obj =& PHP5DBObject::factory($class$array_id$null);
            
$obj->listener($event_name$source$params);
        }
    }
    
    function 
interestedIn($event_name, &$source, &$interested$params = array()) {
        
$l = new Listen();
        
$l->event_name $event_name;
        
$l->source get_class($source) . '@' http_build_query($source->getArrayId());
        
$l->interested get_class($interested) . '@' http_build_query($interested->getArrayId());
        if (
count($params) == 0$l->params '';
        else 
$l->params http_build_query($params);
        
$l->create();
    }


Hecho todo esto, Este es el php que ejecuto.... que pico en varias partes para que se vea su funcionamiento:

Código PHP:

// Incluimos lo necesario
$cup = new Cup();
$cup->setName("TEST Cup");
$cup->create();

$game1 = new Game();
$game1->setCup($cup);
$game1->setPlay_date('2008-03-20');
$game1->setTeam_home(1);
$game1->setTeam_visit(2);
$game1->create();

$game2 = new Game();
$game2->setCup($cup);
$game2->setPlay_date('2008-03-20');
$game2->setTeam_home(3);
$game2->setTeam_visit(4);
$game2->create();

$game3 = new Game();
$game3->setCup($cup);
$game3->setPlay_date('2008-03-21');
$game3->create();
$id $game3->id
Esta primera fase es de inicialización. La BD está así en este punto:

Código PHP:

select 
from game;
+----+--------+---------------------+-----------+------------+--------+--------+
id cup_id play_date           team_home team_visit winner result |
+----+--------+---------------------+-----------+------------+--------+--------+
|  
|      2008-03-20 00:00:00 |         |          |   NULL NULL   |
|  
|      2008-03-20 00:00:00 |         |          |   NULL NULL   |
|  
|      2008-03-21 00:00:00 |      NULL |       NULL |   NULL NULL   |
+----+--------+---------------------+-----------+------------+--------+--------+

select from cup
+----+----------+--------+
id name     winner |
+----+----------+--------+
|  
TEST Cup |   NULL |
+----+----------+--------+ 
Luego establecemos los observers:

Código PHP:

$game3
->setHomeAsWinnerOf($game1);
$game3->setVisitorAsWinnerOf($game2);

$cup->setFinal($game3); 
Para este punto la tabla "listen" ya tiene cargado a los observers:

Código PHP:

select 
from listen
+----+--------------+-----------+------------+---------------+
id event_name   source    interested params        |
+----+--------------+-----------+------------+---------------+
|  
WinnerOfGame Game@id=Game@id=3  setas=home    |
|  
WinnerOfGame Game@id=Game@id=3  setas=visitor |
|  
WinnerOfGame Game@id=Cup@id=1   0=            |
+----+--------------+-----------+------------+---------------+ 
y finalmente, Se juega el torneo :)

Esto lo pongo en el siguiente Post. Que aquí se me acabó el espacio.
__________________
pragone
Blog: Desarrollo, comunidad y monetización
Últimos artículos: Tips de Smarty