Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Singleton, spróbowałem zrobić i niestety nie działa :(
Aztech
post 11.07.2006, 20:01:20
Post #1





Grupa: Zarejestrowani
Postów: 276
Pomógł: 3
Dołączył: 22.10.2003
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


To zacznijmy od początku.
Mam sobie taką klasę bazową (zostawiam najważniejsze elementy)
  1. <?php
  2.  
  3. /**
  4.  * @author Tomasz Suchanek
  5.  * @copyright Tomasz Suchanek 
  6.  * @final 
  7.  */
  8.  
  9. require_once('config.inc.php');
  10. require_once('$RBX_CORE/includes/errors.inc.php');
  11. require_once('$RBX_CORE/includes/constant.inc.php');
  12.  
  13. /**
  14.  * Klasa bazowa dla wszystkich klas
  15.  *
  16.  */
  17. abstract class BaseClass {
  18.  
  19. /**
  20.    * Połaczenie z bazą danych
  21.    *
  22.    * @var array Przechowuje identyfiaktor połączenia z bazą danych.
  23.    * @access private
  24.    */
  25. private $db;
  26.  
  27. /**
  28.    * Wynik zapytania
  29.    *
  30.    * @var array Wynik zapytania skierowanego do bazy
  31.    * @access private  
  32.    */
  33. private $result;
  34.  
  35. /**
  36.    * Zapytanie do bazy
  37.    *
  38.    * @var string Zapytanie kierowane do bazy
  39.    * @access private
  40.    */
  41. private $sql;
  42.  
  43. /**
  44.    * Konstruktor
  45.    * @access public
  46.    */
  47. public function __construct(){
  48.  
  49. global $RBX_DB;
  50.  
  51. # połącz z bazą typu MySQL
  52. $this->db = new PDO('mysql:host='.$RBX_DB['host'].';dbname='.$RBX_DB['name'], $RBX_DB['user'], $RBX_DB['pass']);
  53.  
  54. #polskie litery
  55. $this->setSql('SET NAMES latin2;
  56. SET collation_connection = latin2_general_ci;');
  57. $this->doSQL();
  58.  
  59. # raportuj wszystkie błędy z PDO
  60. $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  61.  
  62. # raportuj wszysrkie błedy z php
  63.  
  64. }
  65.  
  66. /**
  67.    * Ustawia wartości domyślne dla pól prywatnych klasy
  68.    * 
  69.    * @abstract 
  70.    *
  71.    */
  72. abstract public function setDefault();
  73.  
  74. /**
  75.    * Zwróc obiekt połączenia z bazą
  76.    *
  77.    * @return array Tablica z identyfiaktorem połączenia z bazą danych
  78.    * @access public
  79.    */  
  80. public function getDB(){
  81. return $this->db;
  82. }
  83.  
  84. /**
  85.    * Zwraca rezultat zapytania
  86.    *
  87.    * @return array Tablica zawierająca rezultat zapytania
  88.    * @access public
  89.    */
  90. public function getResult(){
  91. return $this->result;
  92. }
  93.  
  94. /**
  95.    * Ustaw zapytanie sql
  96.    *
  97.    * @param string $sql Zapytanie SQL
  98.    * @access public  
  99.    */
  100. public function setSql($sql) {
  101. $this->sql = $sql;
  102. }
  103.  
  104. /**
  105.    * Zwróć treść zapytania
  106.    *  
  107.    * @return string $sql Zapytanie SQL
  108.    */
  109. public function getSql() {
  110. return $this->sql;
  111. }
  112.  
  113. /**
  114.    * Zwróć wyjątek jeśli rezultat zapytania jest pusty
  115.    * 
  116.    * @return true jeśli wynik zapytania jest poprawny
  117.    * @access public
  118.    */
  119. public function checkResult() {
  120. if ($this->result) {
  121. return true;
  122. }
  123. else {
  124. return false;
  125. }
  126. }
  127.  
  128. /**
  129.  * Wywołanie wszytkich metod związanych z wykonaniem zapytanie w jednej funkcji
  130.    * treść zapytania zostaje zapamiętana
  131.    *
  132.    * @param string $sql Zapytanie SQL
  133.    * @access public
  134.    * @return boolean
  135.    */
  136. public function doSQL($sql=''){
  137.  
  138. # gdy niepusty to zapisz zapytanie SQL
  139. if (!empty($sql)) $this->setSql($sql);
  140.  
  141. #wykonaj zapytanie i zapisz do wyników
  142. $stmt = $this->db->prepare($this->getSql());
  143. $stmt->execute();
  144. $this->result = $stmt->fetchAll(PDO::FETCH_ASSOC);
  145. if (isset($this->result[0])) {
  146.  $this->result = $this->result[0];
  147.  } 
  148. $stmt->closeCursor();  
  149. return $this->checkResult();
  150. }
  151. }
  152.  
  153. ?>

i chciałem skorzystać z wzorca Singleton (osatnio czytałem i postanowiłem przerobić to tak, żeby działało)
Więc zrobiłem tak:
$db jest statyczne
  1. <?php
  2. private static $db = false;
  3. ?>

getDB zmieniłem żeby działało jak getIsntance
  1. <?php
  2. public function getDB(){
  3. global $RBX_DB;
  4. if (self::$db == false) {
  5. self::$db = new PDO('mysql:host='.$RBX_DB['host'].';dbname='.$RBX_DB['name'], $RBX_DB['user'], $RBX_DB['pass']);
  6. #polskie litery
  7. $this->doSQL("SET NAMES latin2; SET collation_connection = latin2_general_ci;");
  8. # raportuj wszystkie błędy z PDO
  9. $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  10. }
  11. return self::$db;
  12. }
  13. ?>

a kontruktor teraz wygląda tak
  1. <?php
  2. public function __construct(){
  3.  
  4. global $RBX_DB;
  5.  
  6. $this->getDB();
  7. # raportuj wszysrkie błedy z php
  8. }
  9. ?>

Pozostałość bez zmian.
Mam inne klasy, które dziedziczą po BaseClass i które wywołują w swoim kontruktorze kontruktor rodzica oraz korzystają z $this->doSQL(); Niestety wywołuje too błąd:
Kod
atal error: Cannot access empty property in C:\wamp\www\robotECS\core\classes\baseclass.php on line 141
(to ta linia 143 z pierwszego listingu)

Dlaczego właściwość jest pusta? Pewnie coś robię źle, jeśli tak to co? Czy wywołanie $this->db->jakaśFunkcja() w funkcjach dziedziczacych po baseClass jest porpawne jeśli nie to jak to robić?
Go to the top of the page
+Quote Post
orson
post 11.07.2006, 20:08:14
Post #2





Grupa: Zarejestrowani
Postów: 548
Pomógł: 2
Dołączył: 19.07.2003

Ostrzeżenie: (0%)
-----


witam ...

Zamień $this->db na self:$db - to jest static ... ale też nie wiem czy będzie działać (musisz chyba przepisać to do zmiennej bo nie pamiętam czy można napisać self:biggrin.gifb->metoda)

pozdrawiam


--------------------
Computer games don't affect kids; I mean if <span style="font-weight: bold;">Pac Man</span> affected us as kids,we would all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music.
Go to the top of the page
+Quote Post
Aztech
post 11.07.2006, 20:36:49
Post #3





Grupa: Zarejestrowani
Postów: 276
Pomógł: 3
Dołączył: 22.10.2003
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Zmieniłem wszędzie w klasie bazowej na self::$db i póki co wszystko działa.
Z innej beczki.
Mam klasę User dziedziczącą po BaseClass i funkcję która wywołuje mi coś takiego:
  1. <?php
  2. function getUserInfoById($user_id) {
  3. $user = new User($user_id);
  4. $user->readDataFromSqlById();
  5. $pdo = $user->getDB();
  6. #ilość postów napisanych przez użytkownika
  7. $stmt=$pdo->prepare('SELECT count(*) as posts FROM rbx_posts WHERE author_id='.$user_id);
  8. $stmt->execute();
  9. /* i dalej leci jakiś tam kod ...*/
  10. }
  11. ?>

konstruktor usera wywołuje kostruktor bazowy: parent::__construct()
Jeśli dobrze rozumiem to:
- dzięki temu co napisałem (mam nadieję, że to dobry Singleton jest biggrin.gif) jeśli była stworzona już instancja $db to nie powstanie mi nowa, tylko będę korzystał z już istniejącej
- $pdo = $user->getDB(); zwróci mi do zmiennej $pdo tego static $db dzięki czemu nie postanie żadne nowe połączenie tylko będę korzystał z już istniejącego

Pytanie za 100pkt. Jak sprawdzić czy działa to tak jak napisałem tzn czy mimo wszystko jakimś cudem nie jest tworzone nowe połączenie do bazy?
Go to the top of the page
+Quote Post
orson
post 11.07.2006, 21:02:37
Post #4





Grupa: Zarejestrowani
Postów: 548
Pomógł: 2
Dołączył: 19.07.2003

Ostrzeżenie: (0%)
-----


witam

$user = new User($user_id); daje nowy obiekt ... musisz odwoływać się przez getDB ($user = BaseClass::getDB)

by sprawdzić ile razy tworzy się pdo wewnątrz getDB w ifie daj sobie printa albo jakieś logowanie do pliku

a tak wogóle to powinno być tak: konstruktor powinien być private i do obiektu powieneś się odwoływać tylko przez ::getDB z klas potomnych oraz z zewnątrz ... tworzenie pdo przenieś do konstrukra ... i w getDB tylko zwracanie zapisanej instancji ...

pozdrawiam


--------------------
Computer games don't affect kids; I mean if <span style="font-weight: bold;">Pac Man</span> affected us as kids,we would all be running around in darkened rooms, munching magic pills and listening to repetitive electronic music.
Go to the top of the page
+Quote Post
Aztech
post 11.07.2006, 21:10:13
Post #5





Grupa: Zarejestrowani
Postów: 276
Pomógł: 3
Dołączył: 22.10.2003
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Pobawiłem się trochę moim kodem i okazało się, że chyba nie jest to do końca Singleton albo ja coś spaprałem.
Oto co zrobiłem
BaseClass.php
  1. <?php
  2. /**
  3.    * Połaczenie z bazą danych
  4.    *
  5.    * @var array Przechowuje identyfiaktor połączenia z bazą danych.
  6.    * @access private
  7.    */
  8. private static $db = false;
  9.  
  10. /* ... */
  11.  
  12. /**
  13.    * Konstruktor
  14.    *
  15.    * @access public
  16.    */
  17. public function __construct(){
  18.  
  19. global $RBX_DB;
  20.  
  21. if (self::$db == false) {
  22. self::$db = new PDO('mysql:host='.$RBX_DB['host'].';dbname='.$RBX_DB['name'], $RBX_DB['user'], $RBX_DB['pass']);
  23. # raportuj wszystkie błędy z PDO
  24. self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  25. #polskie litery
  26. #wykonaj zapytanie i zapisz do wyników
  27. $stmt = self::$db->prepare('SET NAMES latin2; SET collation_connection = latin2_general_ci;');
  28. $stmt->execute();
  29. echo '<br>Tworzę połączenie z bazą danych';
  30. }
  31.  
  32. # raportuj wszysrkie błedy z php
  33. }
  34.  
  35. /* ... */
  36.  
  37. /**
  38.    * Zwróc obiekt połączenia z bazą
  39.    *
  40.    * @return array Tablica z identyfiaktorem połączenia z bazą danych
  41.    * @access public
  42.    */  
  43. public static function getDB(){
  44. return self::$db;
  45. }
  46.  
  47. /* ... */
  48.  
  49. /**
  50. * Wywołanie wszytkich metod związanych z wykonaniem zapytanie w jednej funkcji
  51.    * treść zapytania zostaje zapamiętana
  52.    *
  53.    * @param string $sql Zapytanie SQL
  54.    * @access public
  55.    * @return boolean
  56.    */
  57. public function doSQL($sql=''){
  58.  
  59. # gdy niepusty to zapisz zapytanie SQL
  60. if (!empty($sql)) $this->setSql($sql);
  61.  
  62. #wykonaj zapytanie i zapisz do wyników
  63. $stmt = self::$db->prepare($this->getSql());
  64. $stmt->execute();
  65. $this->result = $stmt->fetchAll(PDO::FETCH_ASSOC);
  66. if (isset($this->result[0])) {
  67.  $this->result = $this->result[0];
  68.  } 
  69. $stmt->closeCursor();
  70. return $this->checkResult();
  71. }
  72. ?>

Później podczas logowania wywoływana jest klasa LoginUSer, która dziedziczy po User a ta po BaseClass, loguję się do aplikacji, czyli jest tworzona instancja obiektu user, wywołuje się kontruktor BaseClass.php, można się zatem odwołać do połączenia z bazą poprzez BaseClass:$db i tutaj się myliłem, bo taki kod nie chce mi zadziałąć.
  1. <?php
  2. /**
  3.  * Zwraca listę forów wyświetlanych wg ustalonej kolejności (wg app_order a nie wg id)
  4.  *
  5.  * @return array tablica asocjacyjna
  6.  */
  7. function getForumList()
  8. {
  9. $pdo = BaseClass::getDB();
  10. $stmt=$pdo->prepare("SELECT * FROM rbx_forums AS rf"
  11. ." LEFT JOIN rbx_permissions AS rp ON rf.forum_id=rp.forum_id"
  12. ." WHERE rp.subforum_id=0 AND rp.topic_id=0"
  13. ." ORDER BY rf.app_order ASC"); 
  14. $stmt->execute();
  15. return $stmt->fetchAll(PDO::FETCH_ASSOC);
  16. }
  17. ?>


Czy ma jakiekolwiek znaczenie to, że instancja klasy user jest wywoływana w pliku index.php a getForumList() w rbx.php?

Ten post edytował Aztech 12.07.2006, 18:56:06
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 10.07.2025 - 10:05