Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: widocznosc obiektu wewnątrz klasy
Forum PHP.pl > Forum > PHP
Black-Berry
Czy we wnątrz klasy mogę użyć zewnętrzny obiekt bez konieczności używania deklaracji public ?

  1. <?php
  2. class c_page_creator_main
  3. {
  4. function c_page_creator_main()
  5. {
  6. global $db; //wewnątrz chciałbym użyć ten obiekt bez ciągłego deklorowania go jako public
  7. $db->query( "SELECT * FROM tabela" );
  8.  
  9. }
  10. ?>
webdice
Może dziedziczenie?
Black-Berry
nie ma innego sposobu ?
webdice
  1. <?php
  2. class c_page_creator_main
  3. {
  4. function c_page_creator_main()
  5. {
  6. $db = new myDB ();
  7. $db->query( "SELECT * FROM tabela" );
  8.  
  9. }
  10. ?>
Black-Berry
no tak ale wtedy za kazdym razem bede musiał tworzyc nowy obiekt a to mi ma ułatwić sprawę smile.gif Chodzi o to ze to są odrębne klasy i chciałbym zachoać odrębnoać ale w kazdej linijce pisanie global troche mi się nie widzi.
webdice
Możesz jeszcze przekazywać obiekt do metody.
LonelyKnight
Cytat(Black-Berry @ 13.02.2008, 01:01:28 ) *
Czy we wnątrz klasy mogę użyć zewnętrzny obiekt bez konieczności używania deklaracji public ?

  1. <?php
  2. class c_page_creator_main
  3. {
  4. function c_page_creator_main()
  5. {
  6. global $db; //wewnątrz chciałbym użyć ten obiekt bez ciągłego deklorowania go jako public
  7. $db->query( "SELECT * FROM tabela" );
  8.  
  9. }
  10. ?>



A co złego w tym:

  1. <?php
  2. class c_page_creator_main
  3. {
  4. public $objDB;
  5.  
  6. function c_page_creator_main()
  7. {
  8. $this->objDB = Database::getInstance(); // do bazy danych powinieneś użyć singletona 
  9. $this->objDB ->query( "SELECT * FROM tabela" );
  10.  
  11.  } 
  12.  }
  13. ?>
Black-Berry
@LonelyKnight MAsz u mnie piwo:)
webdice
Dodam że singleton jest porównywany z globalami tylko w ładniejszym opakowaniu.
em1X
po prostu napisz sobie jakiś obiekt podstawowy, który wszystkie inne klasy będą rozszerzać.

  1. <?php
  2. class Object {
  3.  
  4.  public function & getDB() {
  5. // zwraca obiekt mysql
  6.  }
  7.  
  8.  // i tak dalej
  9.  
  10. }
  11. ?>


i w następnych klasach nie będzie problemów:
  1. <?php
  2. class myClass extends Object {
  3.  
  4.  public function display()
  5.  {
  6. $db = $this->getDB();
  7.  
  8. print $db->result('select field from table where id = 1');
  9.  }
  10.  
  11. }
  12. ?>
Black-Berry
@webdicepl Tak sobie myślę... że skoro różnica ma polegać tylko na opakowaniu to już chyba zostanę przy "globalach" i przy kazdym wywołaniu $db dopiszę sobie to global. Nie chcę za dużo komplikować.
webdice
Tak jak Ci mówiłem, tu najlepszym rozwiązaniem będzie dziedziczenie. I tak w metodach używasz funkcji z klasy DB, więc będzie ona nierozłączną częścią Twoich klas.
em1X
Cytat(Black-Berry @ 13.02.2008, 12:15:45 ) *
@webdicepl Tak sobie myślę... że skoro różnica ma polegać tylko na opakowaniu to już chyba zostanę przy "globalach" i przy kazdym wywołaniu $db dopiszę sobie to global. Nie chcę za dużo komplikować.


Używanie globali jest bardzo nieeleganckie, bardzo niepraktyczne i świadczy o niskim poziomie programisty wstydnis.gif . PHP ma całkowicie usunąć w przyszłości funkcję global z języka.
Black-Berry
Rozumiem, W takim razie zrobię tak jak sugerujesz. Obiekt główny i dziedziczące po nim wszystkie inne. To lepszy sposób niż SINGLETON ? Jak uważacie. Zależy mi na dobrym profesjonalnym i przyszłościowym rozwiązaniu, tak żebym mógł pozniej do sterownika bazy dopisać np cache.
em1X
Zauważ, że jeżeli będziesz chciał wprowadzić jakieś modyfikacje do sterownika bazy danych to zrobisz to zupełnie niezależnie od systemu.
Myślę, że rozsądnie jest użyć Singletona w przypadku obsługi bazy danych. Masz wtedy pełną kontrolę nad tym połączeniem z bazą. Ale też (w przypadku innych klas) z nim nie przesadzaj, ostatnio jakaś taka dziwna moda jest na walenie tego Singletona w każdą klasę, gdzie popadnie, a przecież przeważnie ten Singleton wcale nie jest w niej potrzebny.

A więc z głową wszystko, z głową smile.gif

ps. siedzisz dalej w PHP4 ?
Black-Berry
Tak, jakoś tak wyszło, że zaczynałem w PHP4 i się go trzymam. Wiem, że wychodzi już z użycia i nie ma sensu tego ciągnąć, a co do pełnej obiektowości to trochę ona do mnie nie przemawia. Wiem, ze teraz moda na obiekty i wogóle ale kiedy to wszystko się zaczynało to klasa znaczyła grupę obiektów i nikt nie budował całej klasy dla tylko jednego obiektu. Moim zdaniem to trochę nadużycie ale pewnie nie idę z duchem czasu... ale nie o tym:

Przyszło mi do głowy jeszcze jedno rozwiązanie. Co o nim myślicie?

  1. <?php
  2. class c_my_sql_database_driver()
  3. {
  4. function query( $query )
  5. {
  6. //ciało funkci
  7. }
  8. }
  9.  
  10. $object_my_sql_database_driver = new c_my_sql_database_driver();
  11.  
  12. function db_query($query)
  13. {
  14. // ta funkcja będzie mogła w przyszłości przełaczać na inne drivery bazy za pomocą
     switch();
  15. // więc dodatkowo storzę pomost między driverem bazy a klasami.
  16. global $object_my_sql_database_driver;
  17. $object_my_sql_database_driver->query($query);
  18. }
  19.  
  20.  
  21. class c_page_creator()
  22. {
  23. function body_drop()
  24. {
  25.  db_query( 'select coś tam' );
  26. }
  27. }
  28. ?>
em1X
1) Bez sensu.... i skończ z tym globalem w końcu sciana.gif

2) Napisałem Ci jak poprawniej to powinno wyglądać:
http://forum.php.pl/index.php?showtopic=87...rt=#entry441695

Możesz sobie tylko zamienić metodę getDB() na np. query(), która będzie wykonywać zapytania SQL.

3) Poczytaj jak wyglądają klasy w PHP5. Stwarzają masę nowych możliwości. Ludzie jeżdzą samochodami, a Ty dalej razem z Flinstonami na kwadratowych kołach jedziesz snitch.gif

4) przykład:
  1. <?php
  2. abstract class Object {
  3.  
  4. public function getDB()
  5. {
  6. return DB::getInstance();
  7. }
  8.  
  9. }
  10.  
  11. class DB {
  12.  
  13. /**
  14.  * Pola
  15.  */
  16. private static $instance = null;
  17.  
  18. /**
  19.  * Metody
  20.  */
  21. private function __construct() {
  22. $this->connect();
  23. }
  24.  
  25. public function __destruct()
  26. {
  27. $this->disconnect();
  28. }
  29.  
  30. public function getInstance()
  31. {
  32. $class = __CLASS__;
  33. return self::$instance == null ? self::$instance = new $class : self::$instance;
  34. }
  35.  
  36. public function connect()
  37. {
  38. // polacz sie z baza danych
  39. }
  40.  
  41. public function disconnect()
  42. {
  43. // rozlacz sie z baza danych
  44. }
  45.  
  46. public function query($qry)
  47. {
  48. return mysql_query($qry);
  49. }
  50.  
  51. }
  52.  
  53. class TwojaKlasa
  54. extends Object
  55. {
  56. public function display()
  57. {
  58. return $this->getDB()->query('select pole from tabela where pole_id = 1');
  59. }
  60. }
  61.  
  62. /**
  63.  * Przyklad
  64.  */
  65.  
  66. $object = new TwojaKlasa();
  67.  
  68. print $object->display();
  69. ?>
Black-Berry
smile.gif Dobra przekonałes mnie. Postęp musi być biggrin.gif Dzis w nocy zabieram się do analizy tego wszystkiego. Dzięki.


4 godziny później...
Zrobiłem to według schematu. Wszystko działa jak należy:) Jesteś dziś moim bogiem biggrin.gif Jeszcze raz wielkie dzięki!

i jeszcze...
Tak apropo globalsów smile.gif Czy takie coś wchodzi w grę?
  1. <?php
  2. $this->connect_id = @mysql_connect( $GLOBALS["db_host"], $GLOBALS["db_user"], $GLOBALS["db_password"] );
  3. ?>
Tubis
Lepiej by było jakby te db_host, db_user i password były stałymi. Nie miałbyś problemy z ich dostępnąścią w klasach, bo stałe mają widoczność globalną.
Cysiaczek
Może tak jednak nie globale i stałe, a jakiś obiekt konfiguracji?
Black-Berry
Taki obiekt konfiguracyjny były również singletonem prawda? Podobnie jak driver bazy danych ?
Cysiaczek
To już od Ciebie zależy. Może być sigletonem, ale nie musi
Cotter
Ja w tym celu tworzę sobie obiekt globalny w tablicy GLOBALS i w celu skrócenia kodu odwołuję się do niego przez funkcję (nie będącą w żadnej klasie):
  1. <?php
  2. $GLOBALS['sql'] = new Sql();
  3.  
  4. function sql()
  5. {
  6. return $GLOBALS['sql'];
  7. }
  8.  
  9. //i teraz można już używać ten obiekt wszędzie tak:
  10. sql()->query(...);
  11. ?>


Jeżeli zależy nam na singletonie to można oczywiście zastosować zwykły singleton i dopisać sobie taką funkcję:
  1. <?php
  2. function sql()
  3. {
  4. return Sql::getInstance();
  5. }
  6. ?>


Idea polega na tym aby skrócić kod odwołania. Prościej i szybciej jest używać sql()->query() niż Sql::getInstance()->query();

Jeżeli chodzi o tworzenie obiektu nadrzędnego, po którym będą dziedziczyły wszystkie inne to nie polecam tego rozwiązania. W pewnym sensie zmusza ono programistę do dziedziczenia po tej klasie co może czasami okazać się niewygodne.
Black-Berry
no to teraz mi już namieszałeś totalnie smile.gif Znacznie bardziej podoba mi się Twoje rozwiązanie, ale poprzednicy twierdzili zupełnie inaczej.

Przy okazji nasuwa mi się pytanie. Skoro znacznik global ma zostać usunięty z PHP w przyszłości to jak to się ma do tablicy $GLOBALS? tez ma zostać usunięta ?
em1X
No pewnie, że namieszał.

Jeżeli chcesz przechowywać dane konfiguracyjne to zapoznaj się ze wzorcem Registry.

Jeżeli chcesz skrócić sobie notację, możesz utworzyć metodę-osłonkę w swojej klasie:
  1. <?php
  2. class X {
  3.  public function query($sql)
  4.  {
  5.  // przykład
  6.  return $this->getDatabase()->query($sql);
  7.  }
  8. }
  9. ?>
Black-Berry
@em1X tego typu osłonka sprawdza się świetnie. Wielkie dzięki za sugestie. @Cotter Za pomysł ze skróceniem notacji też dziękuję. Wydaje mi się jednak, że obiekt po którym dziedziczą wszystkie inne obiekty to dobry pomysł bo mogę sobie podpinać wtyczki do całego systemu w bardzo wygodny sposób. O to co udało mi się sklecić. Proszę o komentarze.

  1. <?php
  2. abstract class edc_object
  3. {  
  4. /* Pobieranie instancji singletona */
  5. public function db_driver(){ 
  6. return mysql_db_driver::get_instance();
  7. }
  8.  
  9. /* Pomost dla query */
  10. public function query($sql){ 
  11. return $this->db_driver()->query($sql);
  12. }
  13.  
  14. /* Pomost dla result */
  15. public function fetch_row($result=""){ 
  16. return $this->db_driver()->fetch_row($result);
  17. }
  18.  
  19. /* Tutaj zbiór przydatnych funkcji też jako singleton. Nie wiem czy to dobry sposób. */
  20. public function db_functions(){ 
  21. return db_functions::get_instance(); 
  22. }
  23. }
  24. ?>
em1X
1) dużo lepiej niż było na początku czarodziej.gif
Trzeba pisać, pisać i pisać.. wszystko opiera się na doświadczeniu.

2) proponuję kupić sobie tą książkę. Na pewno Ci się przyda, bo wszystko u czym tutaj pobieżnie pisaliśmy, w tej książce jest opisane od podstaw, zaczynając od wzorców projektowych i ciekawych metod programowania obiektowego.
Black-Berry
boje się że mi życia na naukę braknie smile.gif Dzięki wielkie. Zaopatrzę się w nią bo doszedłem chyba do etapu w którym trzeba zmienić swój punkt widzenia o programowaniu w PHP.

Pozdrawiam.
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.