Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [OOP] Używanie atrybutów jednej klasy w drugiej
Forum PHP.pl > Forum > PHP > Object-oriented programming
Still
Witam,
Programuję od jakiegoś roku, ale dopiero od około miesiąca zająłem się OOP i PDO. Mam problem z używaniem atrybutów jednej klasy w drugiej. Konkretniej:

klasa users, ma konstruktor iż pobiera z bazy danych na podstawie cookies (jeżeli są) informacje o użytkowniku takie jak login, adres avatara itp i zapisuje je do swoich atrybutów.

druga klasa wyświetlająca stronę, nazywa się strona. jest w niej funkcja jak wyświetl_początek() i wyświetla ona kod html z logiem, menu. jest też wyswietl_koniec() gdzie rysowana jest stopka.

potrzeba mi użyć w wyświetl_początek() tych pobranych z bazy danych informacji o użytkowniku. jak to rozwiązać?

Fragmenty kodu o jakie się rozchodzi:
  1. class Users
  2. {
  3. private $zalogowany;
  4.  
  5. public function __construct()
  6. {
  7. $this->sprawdz_zalogowanie();
  8. }
  9.  
  10.  
  11. public function sprawdz_zalogowanie()
  12. {
  13. try
  14. {
  15. if( isset($_COOKIE['userid']) && isset($_COOKIE['pass']) )
  16. {
  17. // przygotowanie szkieletu zapytania
  18. $stmt = MySQLDriver::$pdo -> prepare('SELECT * FROM `users` WHERE `id` = :id AND `haslo` = :pass LIMIT 1');
  19.  
  20. $stmt -> bindValue(':id', intval($_COOKIE['userid']), PDO::PARAM_INT);
  21. $stmt -> bindValue(':pass', $_COOKIE['pass'], PDO::PARAM_STR);
  22.  
  23. // wykonanie zapytania
  24. $stmt -> execute();
  25.  
  26. // jeżeli zwróci kogoś z takim id i hasłem
  27. if ($row = $stmt -> fetch(PDO::FETCH_ASSOC))
  28. {
  29. foreach ($row as $k => $v)
  30. {
  31. $this->$k = $v;
  32. }
  33. $stmt -> closeCursor();
  34.  
  35. $this->zalogowany = TRUE;
  36. }
  37. else
  38. {
  39. $this->zalogowany = FALSE;
  40. }
  41. }
  42. else {
  43. $this->zalogowany = FALSE;
  44. }
  45. }
  46. catch(PDOException $e)
  47. {
  48. echo 'Wystapil blad biblioteki PDO: ' . $e->getMessage();
  49. }
  50. }
  51. }


  1. class Strona
  2. {
  3. public $tytul_strony;
  4. public $keywords;
  5.  
  6. public function __construct()
  7. {
  8. MySQLDriver::connect();
  9. }
  10.  
  11. public function wyswietl_poczatek($user)
  12. {
  13. echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n".'<html xmlns="http://www.w3.org/1999/xhtml">'."\n";
  14. $this->wyswietl_head();
  15.  
  16. echo "<body>\n";
  17. ?>
  18. <div id="top">
  19. <a href="index.php"><img src="images/logo.png" width="445" height="160" alt="" /></a>
  20. <div id="logowanie">
  21. <img src="images/avatars/0.gif" hspace="10" style="float:left" alt="" />
  22. <span style="font-size:10px">Jesteś zalogowany jako:</span><br />
  23. <b><?php echo 'Gość'; ?></b>
  24. <span style="font-size:10px"><br /> Przejdź do profilu <br /> Wyloguj</span>
  25. </div>
  26. </div>
  27. <?php
  28. $this->wyswietl_topmenu();
  29. ?>
  30. <!-- treść główna serwisu -->
  31. <table width="1060" border="1" cellpadding="0" cellspacing="0" align="center">
  32. <tr>
  33. <td width="500" rowspan="2" valign="top" align="left">
  34. <!-- lewa główna kolumna -->
  35.  
  36. <!-- wyszukiwarka -->
  37. <?php $this->wyswietl_wyszukiwarka(); ?>
  38. <!-- / wyszukiwarka -->
  39. <?php
  40. }
  41. }


  1. class MySQLDriver
  2. {
  3. public static $pdo;
  4.  
  5. // Nawiązanie połączenia z bazą danych.
  6. public static function connect()
  7. {
  8. self::$pdo = new PDO('mysql:host=localhost;dbname=baza', 'root', '', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
  9. self::$pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  10. }
  11. }


index.php
  1. // załadowanie class
  2. include_once('../classes/mysqldriver.php');
  3. include_once('../classes/users.php');
  4. include_once('../classes/strona.php');
  5.  
  6. // tworzenie obiektów
  7. $strona = new Strona();
  8. $user = new Users();
  9.  
  10. $strona->wyswietl_poczatek();
  11.  
  12. //tutaj tresc danego dzialu
  13.  
  14. $strona->wyswietl_koniec();


Dziękuję za jakąkolwiek pomoc. Pozdrawiam.

PS. Ogólnie to dobrze zrobiłem tą obsługę bazy danych? W tym wypadku wykorzystałem static, ale nie chcę tego nadużywać.
Pilsener
W przypadku takiego kodu ciężko coś doradzić, bo nie wiadomo nawet od czego zacząć winksmiley.jpg Jak masz tak pisać obiektowo, to lepiej już rób to strukturalnie - dobry kod strukturalny jest o niebo lepszy od kiepskiego obiektowego.

Znasz jakieś wzorce projektowe? U Ciebie wszystko w jednym, baza, model danych, jakiś pseudo-widok czy obsługa szablonów, dlatego moje rady są dwie:

1. Zapoznaj się z wzorcami
2. Popatrz, jak robią to popularne frameworki
3. Liźnij trochę teorii (choćby jeśli chodzi o nazewnictwo)
Crozin
Na początek: nie patrz na tym etapie na żadne frameworki. Wzorce również możesz sobie darować bo one nie uczą niczego - pokazują tylko jak rozwiązać pewne popularne problemy: po co Ci rozwiązania problemów, których jeszcze nie masz? smile.gif

1. Tak długo jak to tylko możliwe nie uzależniaj obiektu od danych z zewnątrz (chodzi tu o użycie ciasteczek bezpośrednio w klasie czy konstrukcji typu MySQLDriver::$pdo). To tylko problemy i ogromna utrata elastyczności, w zamian dająca Ci 10 linijek zaoszczędzonego kodu - nie warte. Wymagane zależności (inne obiekty, wymagane do prawidłowego funkcjonowania obiektu: tutaj $pdo) przekaż w konstruktorze, a wymagane dane do działania jakiś metod jako ich argumenty:
  1. class User {
  2. protected $pdo;
  3.  
  4. public function __construct(PDO $pdo) {
  5. $this->pdo = $pdo;
  6. }
  7.  
  8. public function signin($username, $password) {
  9. // ...
  10. $this->pdo->prepare(....);
  11. // ...
  12. }
  1. # index.php
  2.  
  3. $pdo = new PDO(...);
  4. $pdo->setAttribute(...);
  5.  
  6. $user = new User($pdo);
  7.  
  8. if (isset($_COOKIE...)) {
  9. $user->signin($_COOKIE...);
  10. }

2. Unikaj nie potrzebnych klas. Tutaj MySQLDriver nie robi kompletnie nic pożytecznego - po co ona? Utrudnia tylko korzystanie z kodu.
3. Dbaj o obsługę błędów. Takie:
  1. catch(PDOException $e)
  2. {
  3. echo 'Wystapil blad biblioteki PDO: ' . $e->getMessage();
  4. }
Jest nic nie warte. Jedynie utrudnia korzystanie z aplikacji. Takim blokiem catch, który wywala po prostu treść wyjątku można objąć cały skrypt (bo w końcu trzeba zrobić coś z wyjątkami, z którymi nie potrafimy sobie inaczej poradzić).
  1. try {
  2. // cały skrypt strony
  3. } catch (Exception $e) {
  4. var_dump($e); // gdy strona jest już gotowa do działania na prawdziwym serwerze zamieniamy to na:
  5. // zapisanie błędu do logów
  6. // die('Coś poszło nie tak. Spróbuj ponownie za chwilę');
  7. }
Jeżeli jakiegoś wyjątku nie jesteśmy w stanie obsłużyć - nie robimy tego. Być może jakiś "wyższy" (w hierarchii) blok try {} catch {} będzie w stanie to zrobić. Jeżeli nie to może kolejny. Jeżeli nadal nie, to dotrze to do tego obejmującego całą stronę i wywali się na ekran.
4. Daruj sobie póki co jakiekolwiek klasy do wyświetlania strony. Można takie tworzyć, ale muszą być one naprawdę potężne (pod względem skomplikowania). Używaj póki co typowych szablonów.
5. Popracuj nad nazewnictwem.
Still
Cytat(Pilsener @ 12.10.2010, 23:33:15 ) *
W przypadku takiego kodu ciężko coś doradzić, bo nie wiadomo nawet od czego zacząć winksmiley.jpg Jak masz tak pisać obiektowo, to lepiej już rób to strukturalnie - dobry kod strukturalny jest o niebo lepszy od kiepskiego obiektowego.

Znasz jakieś wzorce projektowe? U Ciebie wszystko w jednym, baza, model danych, jakiś pseudo-widok czy obsługa szablonów, dlatego moje rady są dwie:

1. Zapoznaj się z wzorcami
2. Popatrz, jak robią to popularne frameworki
3. Liźnij trochę teorii (choćby jeśli chodzi o nazewnictwo)

Zgadzam się z tym, dlatego przychodzę tu na forum o radę, bo jednak wolę się rozwijać i opanować te pisanie obiektowo niż cały czas siedzieć w strukturalnym. smile.gif
Przeczytałem dzisiaj o wzorach projektowych w książce "Programowanie obiektowe w PHP5" Hasina Hayder, ale nic użytecznego z tego nie wyciągnąłem...


Cytat(Crozin @ 13.10.2010, 10:06:53 ) *
Na początek: nie patrz na tym etapie na żadne frameworki. Wzorce również możesz sobie darować bo one nie uczą niczego - pokazują tylko jak rozwiązać pewne popularne problemy: po co Ci rozwiązania problemów, których jeszcze nie masz? smile.gif

1. Tak długo jak to tylko możliwe nie uzależniaj obiektu od danych z zewnątrz (chodzi tu o użycie ciasteczek bezpośrednio w klasie czy konstrukcji typu MySQLDriver::$pdo). To tylko problemy i ogromna utrata elastyczności, w zamian dająca Ci 10 linijek zaoszczędzonego kodu - nie warte. Wymagane zależności (inne obiekty, wymagane do prawidłowego funkcjonowania obiektu: tutaj $pdo) przekaż w konstruktorze, a wymagane dane do działania jakiś metod jako ich argumenty:

Dobra rady, dzięki smile.gif

Cytat(Crozin @ 13.10.2010, 10:06:53 ) *
2. Unikaj nie potrzebnych klas. Tutaj MySQLDriver nie robi kompletnie nic pożytecznego - po co ona? Utrudnia tylko korzystanie z kodu.

W takim razie na każdej podstronie na początku dawać includem jakiś plik, który będzie mi wykonywał "$pdo = new PDO(...); $pdo->setAttribute(...);" ?

Cytat(Crozin @ 13.10.2010, 10:06:53 ) *
4. Daruj sobie póki co jakiekolwiek klasy do wyświetlania strony. Można takie tworzyć, ale muszą być one naprawdę potężne (pod względem skomplikowania). Używaj póki co typowych szablonów.

Mógłbyś rozwinąć swoją myśl "typowych szablonów" ? Stworzyłem już layout strony, pociąłem go i wklepałem w xHTML i CSS. Skoro nie tak mam go zaimplementować, to jak? smile.gif

Jeżeli chodzi o funkcję sprawdz_zalogowanie(), to zostaje ona wywołana za każdym razem ładowania strony. Chodzi o to, aby sprawdzić czy cookies jakie użytkownik ma w przeglądarce, służą zalogowaniu do serwisu. Zakładamy że wypełnił on już formularz logowania i ciasteczka już sobie tam leżą. Uważam, że takie sprawdzenie trzeba wykonać za każdym razem ładowania strony. Chyba w tym wypadku nie przeszkadza to iż sprawdzenie czy istnieją leży po stronie metody za to odpowiedzialnej? Bo jeżeli ich nie ma to po prostu wrzuca false i tyle smile.gif Pozdrawiam.
Crozin
Cytat
Mógłbyś rozwinąć swoją myśl "typowych szablonów" ? Stworzyłem już layout strony, pociąłem go i wklepałem w xHTML i CSS. Skoro nie tak mam go zaimplementować, to jak?
Ot, zwykły plik z szablonem:
  1. <body>
  2. <h1>Witaj <?php echo $username ?></h1>
  3. </body>
I coś co pozwoli na chociażby najprostsze operacje na tym:
  1. function abc($template, array $vars = array()) {
  2. extract($vars);
  3. include($template);
  4. }


Cytat
W takim razie na każdej podstronie na początku dawać includem jakiś plik, który będzie mi wykonywał "$pdo = new PDO(...); $pdo->setAttribute(...);" ?
Możesz to zrobić tak, możesz też mieć jeden plik (googleaj za: Front Controller) do którego będzie kierowany cały ruch strony, a on już sobie wczyta podpowiednie podstrony.
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.