Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Prosta gra na klasie
Forum PHP.pl > Forum > Przedszkole
mimol
Witam. Napisałem sobie klasę game
  1. <?php
  2. class Game
  3. {
  4. private $number;
  5. private $try;
  6. private static $instance;
  7.  
  8. public static function getInstance()
  9. {
  10. if(self::$instance === null) {
  11. self::$instance = new Game();
  12. }
  13. return self::$instance;
  14. }
  15.  
  16. public function __construct()
  17. {
  18. $this->number = rand(1, 100);
  19. $this->try = 1;
  20. }
  21.  
  22. public function type($type)
  23. {
  24. if ($type == $this->number){
  25. echo 'Gratz. You need '.$this->try.' tries';
  26. } elseif ($type < $this->number){
  27. echo 'Select greater number';
  28. } else {
  29. echo 'Select smaller number';
  30. }
  31. $this->try++;
  32. }
  33. }
  34.  
  35. ?>

No i oczywiście plik z formularzem.
  1. <?php
  2. require 'game.php';
  3.  
  4. if (isset($_SESSION['game'])) {
  5. $game = unserialize($_SESSION['game']);
  6. } else {
  7. echo 'set';
  8. $game = Game::getInstance();
  9. $_SESSION['game'] = serialize($game);
  10. }
  11.  
  12. echo '<html><head><title>The Game</title></head><body>';
  13. echo '<form method="GET" enctype="text/plain">
  14. Number: <input type="text" name="number" pattern="\d*" />
  15. <input type="submit" />
  16. </form>';
  17.  
  18. if (isset($_GET['number'])) {
  19. $type = $_GET['number'];
  20. $game->type($type);
  21. }
  22.  
  23. ?>
  24. </body></html>

Moje pytanie brzmi, czy da to się łatwiej zrobić? (bez wykorzystywania sesji, raz ustawić obiekt i potem cały czas z niego korzystać) Po co używać wzorca singleton. Przecież podczas pisania kodu, osoba, która go pisze wie czy utworzyła już dany obiekt czy nie...
CuteOne
Praktyczny przykład wykorzystania singletona
  1. class MojSingleton {}
  2.  
  3. class InnaKlasa{
  4.  
  5. public function add() {
  6. $mojSingleton = MojSingleton:: getInstance();
  7. }
  8. }



Właściwie po co ci ta klasa game? I w jakim celu zapisujesz ją do sesji zamiast stworzyć osobny obiekt dla sesji i wrzucać do niego dane z game?
mimol
Mógłbyś napisać jak to osiągnąć?
W klasie game, mam tworzyć sesje, a w formularzu ją odczytywać?
CuteOne
Obiekt powinien zajmować się tylko jedną rzeczą, więc nie staraj się tworzyć klasy od wszystkiego.

- stwórz klasę przechowującą sesje (google session class example)
- niech game odpowiada tylko za siebie i za pomocą getterów pobieraj od niej dane do klasy obsługującej sesję
mimol
Nie za bardzo rozumiem... Nie chcę tworzyć klasy sesji na siłę... czy to jest rzeczywiście konieczne?
Wsadzam obkiet Game do sesji ponieważ chcę skorzystać z funkcji type().
Czy według ciebie powinienem w sesji zapisywać number, try?? Co jeśli obiekt przechowuje więcej danych, wtedy będzie mały bałagan, za każdym razem odczytwać te dane...
Mógłbyś mi to troszkę jaśniej wytłumaczyć?

Najprostsza klasa sesji, którą udało mi się znaleźć TU czy jest ona wystarczająca? (Po przerobieniu na PHP5)
lub TU
Crozin
1. Nie potrzebujesz korzystać z własnej klasy obsługi sesji. Domyślny mechanizm wbudowany w PHP w pełni tutaj wystarczy.
2. Nie ma potrzeby ręcznie (de)serializować obiektów "wrzucanych do sesji". Cała tablica $_SESSION i tak jest (de)serializowana przy zapisie/odczycie z pliku/pamięci.
3. Nie ma tutaj ani jednego powodu dla którego miałbyś korzystać z singletona, nie powinieneś tego robić. Przykład "praktycznego wykorzystania singletona" podany przez @CuteOne to jeden z paskudniejszych potworków jakie można umieścić w swoim kodzie - takiego czegoś również nie powinieneś praktykować. wink.gif
4. Odpowiadając na Twoje pytanie: musisz ręcznie umieścić obiekt w sesji i ręcznie go stamtąd odczytać. Nie mniej jednak możesz troszkę uprościć swój kod:
  1. <?php
  2.  
  3.  
  4. if (!isset($_SESSION['game'])) {
  5. $_SESSION['game'] = new Game();
  6. }
  7.  
  8. $game = $_SESSION['game'];
  9.  
  10. if (isset($_GET['type'])) {
  11. $game->type($_GET['type']);
  12. }
  13.  
  14. // formularz
5. Właściwość Game::try powinna nazywać się Game::tries, a komunikat o wygranej brzmieć: You needed n tries..
6. Metoda Game::type nie powinna raczej wyświetlać komunikatów tylko zwracać informację o wyniku swojego działania. Tutaj najlogiczniejszym wydaje się zwrócenie liczby mniejszej od zera w przypadku podania za małej liczby, większej od zera w przypadku za dużej i w końcu zera w przypadku trafienia. Dzięki temu Twoja klasa będzie bardziej uniwersalna - będziesz mógł ją wykorzystać w dowolny sposób, nie tylko w tym jednym konkretnym formularzu.
mimol
Cytat
Nie ma potrzeby ręcznie (de)serializować obiektów "wrzucanych do sesji".
Też mi się tak wydaje
Jednak jeśli nie serializuje to dostaje error
  1. Fatal error: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "Game" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in C:\xampp\htdocs\game\index.php on line 19

Dlaczego w tym przypadku muszę recznie serializować ? Czy może jest inny sposób na pozbycie się tego błędu?


  1. <?php
  2. require 'game.php';
  3.  
  4. if (!isset($_SESSION['game'])) {
  5. $_SESSION['game'] = new Game();
  6. }
  7.  
  8. $game = $_SESSION['game'];
  9.  
  10. echo '<html><head><title>The Game</title></head><body>';
  11. echo '<form method="POST">
  12. Number: <input type="text" name="number" pattern="\d*" />
  13. <input type="submit" />
  14. </form>';
  15.  
  16. if (isset($_POST['number'])) {
  17. $type = $_POST['number'];
  18. $game->type($type);
  19. }
  20.  
  21. ?>
  22. </body></html>


Pojawia się jeszcze jeden problem, którego nie przemyślałem... Z tym, że zawsze obiekt odczytuje z sesji, nigdy nie zwiększa się liczba prób, w tym wypadku można to rozwiązać na 2 sposoby.
a) Zapisywać liczbę prób w sesji.
cool.gif za każdym razem zapisywać obiekt do sesji.
Który lepszy?
Crozin
1. W momencie wywołania funkcji session_start() następuje odczytanie i deserializacja danych z pliku (czy gdziekolwiek przechowujesz dane). W swoim kodzie nie zdefiniowałeś żadnego autoloadera, a klasę Game wczytujesz dopiero po wystartowaniu sesji, więc PHP nie ma pojęcia jak zdeserialiozwać obiekt typu Game, bo nie zna typu Game. Powinieneś skorzystać z autoloadera, albo przenieść wczytanie pliku game.php przed session_start().
2. Powinieneś raczej wrzucać cały obiekt do sesji. Gdy pojawią się nowe właściwości w grze nie będziesz musiał przynajmniej bawić się w modyfikowanie mechanizmu gry nigdzie poza samą klasą Game.
3. Jeżeli decydujesz się na wrzucenie obiektu do sesji powinieneś raczej implementować przy nim interfejs Serializable.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.