2012-09-18 12 views
5

Sto lavorando a un sito Web di giochi Flash. Ho due modelli: Gioco e Utente e una tabella intermedia in cui tengo le azioni dell'utente come ad esempio: "Utente 1 ama Gioco 3".Le migliori pratiche per la funzionalità "mi piace"

  1. Dove è il posto migliore per la mia funzione simile?
  2. È buona norma acquisire l'ID utente corrente nel modello Gioco? o dovrei passarlo come parametro?

Per motivi di prestazioni, si aumenta anche il campo dei Mi piace nella tabella di gioco. Ho omesso di controllare se l'utente apprezza già il gioco solo per mantenerlo semplice.
Qui ci sono le mie opzioni:

Prima versione:

$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(); 
    } 
} 

Seconda versione:

$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

'È una buona pratica catturare l'id utente attuale nel modello di gioco?' No. 'o dovrei passarlo come parametro?' Sì. Pensaci, adesso memorizzi l'ID dell'utente attivo nella sessione, cosa succede se in seguito lo memorizzi da qualche altra parte? Ancora più importante, la tua funzione è utilizzabile solo per l'utente attivo corrente, non puoi 'like()' per nessun altro utente. L'id utente è una dipendenza esterna, non c'è assolutamente alcun motivo per legare il tuo modello di gioco ad esso, letto su [dipendenza da iniezione] (http://en.wikipedia.org/wiki/Dependency_injection). – yannis

risposta

1

Per essere onesto, non sono sicuro se questo è il posto migliore per una domanda come questo. Forse la visione del codice è una soluzione migliore. A parte tutto, IMO, nessuna delle due proposte suggerite è "l'approccio migliore". Ma come sempre, quella potrebbe essere una cosa personale.
Dal mio punto di vista, il modo migliore per andare su OOP è quello di inserire tutti i dati negli oggetti ASAP e implementare un livello di servizio che si occupa delle operazioni che richiedono più query o più oggetti.

Se si presume che si stia utilizzando un pattern MVC-ish, il controller riceve i dati. Qui, si istanzia un oggetto Game e si imposta l'ID su 123456. È possibile passare quell'istanza a un metodo di servizio denominato fillGameModel(Game $gameInstance). Questo metodo si collega al DB e imposta tutte le altre proprietà dell'oggetto Game e lo restituisce. Lo stesso vale per l'oggetto User. Entrambi questi oggetti possono quindi essere passati a un altro metodo di servizio: likeGame(Game $game, User $user). Questo metodo può prendersi cura del resto.
Personalmente, farei ancora un passo avanti e usare i mapper per l'accesso al mio DB, ma non ne parlerò ora. Ecco un esempio utilizzando un servizio, e un altro approccio 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'); 
} 

Nuovamente, i loop attraverso il gruppo di risultati potrebbero essere sostituiti da un metodo in una classe modello astratto che prende un array come argomento, e trasforma i fieldnames per i loro setter corrispondenti. Un sacco di spazio per l'astrazione, direi ;-)

Problemi correlati