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: 18 años, 9 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($params, true) . "</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($params, true) . "</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_name, get_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->interested, 2);
            
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 |
+----+--------+---------------------+-----------+------------+--------+--------+
|  
1 |      1 | 2008-03-20 00:00:00 |         1 |          2 |   NULL | NULL   |
|  
2 |      1 | 2008-03-20 00:00:00 |         3 |          4 |   NULL | NULL   |
|  
3 |      1 | 2008-03-21 00:00:00 |      NULL |       NULL |   NULL | NULL   |
+----+--------+---------------------+-----------+------------+--------+--------+

select * from cup
+----+----------+--------+
| 
id | name     | winner |
+----+----------+--------+
|  
1 | 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        |
+----+--------------+-----------+------------+---------------+
|  
1 | WinnerOfGame | Game@id=1 | Game@id=3  | setas=home    |
|  
2 | WinnerOfGame | Game@id=2 | Game@id=3  | setas=visitor |
|  
3 | WinnerOfGame | Game@id=3 | 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