2012-09-18 22 views
5

Estoy trabajando en un sitio web de juegos flash. Tengo dos modelos: Juego y Usuario y una tabla intermedia en la que mantengo las acciones del usuario como por ejemplo: "Usuario 1 me gusta Juego 3".Mejor práctica para la funcionalidad 'me gusta'

  1. ¿Dónde está el mejor lugar para mi función como?
  2. ¿Es una buena práctica obtener la identificación de usuario actual en modelo de juego? o debería pasarlo como parámetro?

Por razones de rendimiento, también incremente el campo "Me gusta" en la tabla de juegos. He omitido verificar si al usuario ya le gusta el juego solo para hacerlo simple.
Éstos son mis opciones:

Primera versión:

$user->like(12345); 

class User 
{ 
    public function like($game_id) 
    { 
    $like = new User_Game(); 
    $like->user_id = $this->id; 
    $like->game_id = $game_id; 
    $like->save(); 

    $obj = new Game($game_id); 
    $obj->likes++; 
    $obj->save(); 
    } 
} 

Segunda versión:

$game->like(); // by current user 

class Game 
{ 
    public function like() 
    { 

    $like = new User_Game();  
    $like->user_id = $_SESSION[‘user_id’];  
    $like->game_id = $this->id;  
    $like->save(); 

    $this->likes++;  
    $this->save();  
    }  
}  
+0

'¿Es una buena práctica tomar el ID de usuario actual en el modelo de juego?' No. '¿o debería pasarlo como parámetro?' Sí. Piénselo, ahora mismo almacena la identificación de su usuario activo en la sesión, ¿qué ocurre si más tarde la almacena en otro lugar? Lo que es más importante, su función solo se puede usar para el usuario activo actual, no puede 'like()' para ningún otro usuario. La identificación del usuario es una dependencia externa, no hay absolutamente ninguna razón para vincular su modelo de juego, lea en [inyección de dependencia] (http://en.wikipedia.org/wiki/Dependency_injection). – yannis

Respuesta

1

para ser perfectamente honesto, no estoy seguro de si este es el mejor lugar para una pregunta como esto. Quizás la revisión de código sea una mejor opción. Dejando a un lado todas las cosas, IMO, ninguna de las dos tomas que sugiera es "el mejor enfoque". Pero como siempre, eso podría ser algo personal.
En mi opinión, la mejor manera de realizar OOP es insertar todos sus datos en objetos lo antes posible e implementar una capa de servicio que se encargue de las operaciones que requieren varias consultas o varios objetos.

Si puedo asumir que está utilizando un patrón MVC-ish, su controlador recibe los datos. Allí, creará una instancia de un objeto Game y establecerá el ID en 123456. Puede pasar esa instancia a un método de servicio llamado fillGameModel(Game $gameInstance). Este método se conecta a la BD y establece todas las demás propiedades del objeto Game y lo devuelve. Lo mismo ocurre con el objeto User. Ambos objetos se pueden pasar a otro método de servicio: likeGame(Game $game, User $user). Ese método puede encargarse del resto.
Personalmente, iría incluso un paso más allá y usaría mapeadores para mi acceso de base de datos, pero no entraré en eso ahora. Aquí hay un ejemplo el uso de un servicio, y un enfoque más OO:

//controller: 
$user = new User(); 
$user->setId($_SESSION['user_id']); 
$game = new Game(); 
$game->setId(123456);//wherever you get this from 
$service = new MainService(); 
$service->userLikes($game,$user); 

//service: 
public function userLikes(Game $game, User $user) 
{ 
    $user = $this->_completeUser($user); 
    $game = $this->_completeGame($game); 
    //insert or update whatever data you need... 
} 

protected function _completeUser(User $user) 
{ 
    $db = $this->_getConnection();//asuming PDO, to keep things simple 
    $query = 'SELECT * FROM my_db.users WHERE id = ?'; 
    $stmt = $db->prepare($query); 
    $row = $stmt->fetch(PDO::FETCH_ASSOC); 
    foreach ($row as $field => $value) 
    {//this implies getters and setters in your model 
     $user->{'set'.ucfirst(strtolower($field))}($value); 
    } 
    return $user; 
} 

protected function _completeGame(Game $game) 
{ 
    $db = $this->_getConnection(); 
    $query = 'SELECT * FROM my_db.games WHERE id = ?'; 
    $stmt = $db->prepare($query); 
    $row = $stmt->fetch(PDO::FETCH_ASSOC); 
    foreach ($row as $field => $value) 
    {//field id becomes "setId" method, field name "setName" etc... 
     $game->{'set'.ucfirst(strtolower($field))}($value); 
    } 
    return $game; 
} 

//just for show: a pseudo-overloader method, if your models all share the same 
//abstract class. 
protected function _completeAny(Model_Abstract $model) 
{ 
    $modelName = get_class($model); 
    if (method_exists($this,'_complete'.$modelName)) 
    { 
     return $this->{'_complete'.$modelName}($model); 
    } 
    throw new Exception('No completion method for '.$modelName.' found'); 
} 

Una vez más, los bucles a través del conjunto de resultados podrían ser reemplazados con un método en una clase de modelo abstracto que toma una matriz como argumento, y transforma los nombres de campos a sus setters correspondientes. Mucho espacio para la abstracción, diría ;-)

Cuestiones relacionadas