2012-09-18 12 views
5

Pracuję nad stroną z grami flash. Mam dwa modele: Gra i Użytkownik oraz tabelę pośrednią, w której przechowuje się akcje użytkownika, na przykład: "Użytkownik 1 lubi grę 3".Najlepsza praktyka dla funkcji "podobnych"

  1. Gdzie jest najlepsze miejsce do mojej podobnej funkcji?
  2. Czy to dobra praktyka, aby pobrać bieżący identyfikator użytkownika w modelu Game? czy powinienem przekazać to jako parametr?

Ze względu na wydajność, to zwiększamy pole lubi w tabeli gra zbyt. Nie podjąłem sprawdzania, czy użytkownik lubi grę, aby była prosta.
Oto moje opcje:

Pierwsza wersja:

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

Druga wersja:

$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

'Czy to dobra praktyka, aby chwycić bieżący identyfikator użytkownika w modelu gry?' No. 'czy powinienem przekazać go jako parametr?' Tak. Pomyśl o tym, teraz przechowujesz identyfikator aktywnego użytkownika w sesji, co się stanie, jeśli później będziesz przechowywać go gdzieś indziej? Co ważniejsze, twoja funkcja jest użyteczna tylko dla bieżącego aktywnego użytkownika, nie możesz 'lubić()' dla jakiegokolwiek innego użytkownika. Identyfikator użytkownika jest zewnętrzną zależnością, nie ma absolutnie żadnego powodu, aby wiązać z nim swój model gry, przeczytać na [wtrysk zależności] (http://en.wikipedia.org/wiki/Dependency_injection). – yannis

Odpowiedz

1

Szczerze mówiąc, nie jestem pewien, czy jest to najlepsze miejsce na pytanie tak jak to. Być może kodereview jest lepszym rozwiązaniem. Niezależnie od tego, IMO, żadna z tych dwóch opcji nie sugeruje, że jesteś "najlepszym podejściem" "najlepsze podejście". Ale jak zwykle to może być sprawa osobista.
Moim zdaniem, najlepszym sposobem na uzyskanie OOP, jest przekazanie wszystkich danych w obiektach ASAP i wdrożenie warstwy usługi, która zajmuje się operacjami, które wymagają wielu zapytań lub kilku obiektów.

Jeśli mogę założyć, że używasz wzorca MVC, kontroler odbiera dane. Tam należy utworzyć instancję obiektu Game i ustawić identyfikator na 123456. Możesz przekazać to wystąpienie do metody serwisowej o nazwie fillGameModel(Game $gameInstance). Ta metoda łączy się z bazą danych i ustawia wszystkie inne właściwości obiektu Game i zwraca ją. To samo dotyczy obiektu User. Oba te obiekty można następnie przekazać do innej metody serwisowej: likeGame(Game $game, User $user). Ta metoda może zająć się resztą.
Osobiście posunąłbym się o krok dalej i użyłbym maperów do mojego dostępu do bazy danych, ale nie wchodzę w to teraz. Poniżej znajduje się przykład korzystania z usługi, a bardziej podejście 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'); 
} 

Ponownie, pętle poprzez wynikowego można zastąpić metody w abstrakcyjnej klasie modelu, która pobiera tablicę jako argument i przekształca fieldnames do ich odpowiednie setery. Miałem dużo miejsca na abstrakcję ;-)

Powiązane problemy