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ę ;-)
'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