Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Dynamiczna nazwa klasy
Forum PHP.pl > Forum > PHP > Object-oriented programming
Bajki
Witam
Mam taką linijke w kodzie :
  1. getRecent::getContent();


jednak potrzebuje aby nazwa klasy była wczytywana ze zmiennej (znajduje się ona w $this->module->action)

Zastosowanie
  1. $this->module->action::getContent();

nie działa a więc albo jest to nie możliwe albo istnieje na to jakiś sprytny sposób, którym się mam nadzieje ze mną podzielicie smile.gif

Znalazłem w internecie kilka wyjaśnień jak się z tym uporać jednak żadne z nich nie działało

Pozdrawiam i z góry dziękuje za pomoc!
Crozin
Skorzystaj z ReflectionAPI.
marcio
Jesli jako nazwe funckji podasz $this -> costam tez nie dziala spruboj tak:

  1.  
  2. $action = $this->module->action;
  3.  
  4. $action::getContent();
  5.  


Bajki
przy podaniu zmiennej otrzymuje
Cytat
Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in /var/www/opencart/api/lib.class.php on line 60


winksmiley.jpg czyli to samo co przy $this->module->action
LBO
call_user_func
Bajki
ok wygląda na to, że ta funkcja załatwia sprawę jednak pojawiają się pewne komplikacje.
Kiedy używałem
Cytat
getRecent::getContent();

nie pojawiały się żadne błędy, jednak gdy używam call_user_func (która chyba robi to samo?) otrzymuje :
Cytat
Fatal error: Using $this when not in object context in /var/www/opencart/api/modules/shop/products/getPopular.php on line 8

Klasa nazywa się getRecent i jest includowana przez require_once() z zewnętrznego pliku wyglądającego tak :
  1. <?php
  2.  
  3. class getRecent extends Core
  4. {
  5.  
  6. function getContent()
  7. {
  8. $this->db("SELECT product_id, model, image, price, date_added FROM {$this->config->db_prefix}product ORDER BY date_added DESC LIMIT {$this->limit_begin},{$this->limit_end}");
  9. }
  10.  
  11.  
  12. }


chciał bym wiedzieć czy problem wynika z błędnej konstrukcji skryptu czy z tego, że call_user_func działa inaczej niż mi się wydaje.
Jeśli to potrzebne, opiszę dokładniej strukturę całego skryptu.
LBO
Najpierw musisz zainicjalizować getRecent, czyli

  1. $action = new $this->module->action;
  2.  
  3. // dalej ustawić obiekt odpowiedzialny za zapytania na
  4. // bazie danych - ten do którego odwołujesz się $this->db
  5.  
  6. $content = $action->getTontent();


edit:

$this->db to nawet nie obiekt.... powinieneś przeprojektować ten swój systemik.
Bajki
hehe no właśnie na razie się bawie z projektowaniem obiektowym i tworzeniem klas więc to może wszystko kiepsko wyglądać winksmiley.jpg w każdym bądź razie zależy mi, żeby klasy typu getRecent czy getPopular były w osobnym pliku (to ma być coś w rodzaju pluginów). Na dobrą sprawe w tych zewnętrznych plikach mógł bym umieszczać samo zapytanie ale chyba stworzenie z tego całej klasy stwarza większe możliwości na przyszłośc ? winksmiley.jpg

Ogólnie cały skrypt wygląda tak, że mam klasę Core w której umieściłem różne funkcje...m.in. getModule któ¶a wygląda tak :
  1. function getModule( $module = null )
  2. {
  3. if(empty($module)) {
  4. $this->makeError(2);
  5. return 0;
  6. }
  7.  
  8. $module = trim($module);
  9.  
  10. if(!eregi("^([a-zA-Z])+\\.([a-zA-Z])+\\.([a-zA-Z])+$", $module)) {
  11. $this->makeError(3);
  12. return 0;
  13. }
  14.  
  15. $module = explode('.', $module);
  16. $this->module->name = $module[0];
  17. $this->module->category = $module[1];
  18. $this->module->action = $module[2];
  19.  
  20. if( !file_exists("modules/{$this->module->name}/{$this->module->category}/{$this->module->action}.php") ) {
  21. $this->makeError(4);
  22. return 0;
  23. }
  24.  
  25. require_once("modules/{$this->module->name}/{$this->module->category}/{$this->module->action}.php");
  26.  
  27. #$action = new $this->module->action;
  28. #$action->getContent();
  29.  
  30. $action = $this->module->action;
  31.  
  32. call_user_func(array($action, 'getContent'));
  33. #$action::getContent();
  34.  
  35. return 1;
  36. }


funkcja ta, na podstawie $_GET['module'] wczytuje/includuje odpowiedni plik z klasą

Czy Twoje rozwiązanie tyczy się właśnie tej funkcji ? tzn. czy podane przez Ciebie linijki mam dokleić do tej funkcji ? Kiedy to robie, otrzymuje absurdalne błędy przy połączeniu z mysqlem. Funkcja db() wygląda następująco :
  1. function db( $query )
  2. {
  3. $result = @mysql_connect($this->config->db_hostname, $this->config->db_username, $this->config->db_password) or $this->makeError(5);
  4. $result = @mysql_select_db($this->config->db_database) or $this->makeError(5);
  5.  
  6. $query = mysql_query($query) or $this->makeError(6);
  7.  
  8. if($this->error->code == null)
  9. {
  10. $this->num_rows = mysql_num_rows($query);
  11. $i = 1;
  12. while($row = mysql_fetch_assoc($query))
  13. {
  14. $this->result[$i] = $row;
  15. $i++;
  16. }
  17. $this->query = $query;
  18. }
  19.  
  20. }


przed zastosowaniem Twojego rozwiązania skrypt łączy się pomyślnie jednak kiedy dokleje linijki, otrzymuje :
Cytat
Warning: mysql_query() [function.mysql-query]: Access denied for user 'www-data'@'localhost' (using password: NO) in /var/www/opencart/api/lib.class.php on line 124

Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in /var/www/opencart/api/lib.class.php on line 124

Warning: Cannot modify header information - headers already sent by (output started at /var/www/opencart/api/lib.class.php:124) in /var/www/opencart/api/lib.class.php on line 71


I nie mam pojęcia co mają wspólnego te linijki z połączeniem...to się wydaje absurdalne ale rozumiem, że na pewno popełniłem jakiś idiotyczny błąd lub czegoś nie rozumiem winksmiley.jpg
LBO
Zakładam, że nie masz ustawionego

  1. $this->config
Bajki
oczywiście. Dokładniej w ten sposób :
  1. function getShopConfig( $file )
  2. {
  3. if( !file_exists($file) ) {
  4. $this->makeError(0);
  5. return 0;
  6. }
  7.  
  8. require_once($file);
  9.  
  10. $this->config->db_driver = DB_DRIVER;
  11. $this->config->db_hostname = DB_HOSTNAME;
  12. $this->config->db_username = DB_USERNAME;
  13. $this->config->db_password = DB_PASSWORD;
  14. $this->config->db_database = DB_DATABASE;
  15. $this->config->db_prefix = DB_PREFIX;
  16.  
  17. return 1;
  18.  
  19. }

+
  1. $config = $api->getShopConfig('../config.php');
LBO
Ale na obiekcie Core, a nie getRecent prawda?
Bajki
zgadza się winksmiley.jpg
LBO
Czyli na drodze dalszej dedukcji mogę założyć, że już wiesz - dzięki wnikliwej analizie - w czym tkwi problem? smile.gifsmile.gifsmile.gif
Bajki
hehe no tak domyślam się ale nie całkiem rozumiem dlaczego winksmiley.jpg ogólnie myślę (niekoniecznie dobrze), że kod
  1. class getRecent extends Core{}

oznacza, że klasa getRecent dziedziczy 'wszystko' z klasy Core. A jeśli tak, to dlaczego nie moge użyć zmiennych ? Do tego znajdujących się w w tej samej klasie(Core) co funkcja odpowiedzialna za zapytanie SQL ?
LBO
już ci pokazuje:
  1. class A
  2. {
  3. public $property;
  4. }
  5.  
  6. class B extends B
  7. {}
  8.  
  9. $a = new A;
  10. print $a->property; // nic
  11.  
  12. $a->property = 'A';
  13. print $a->property; // A
  14.  
  15. $b = new B;
  16. print $b->property; // nic, a ty pewnie się spodziewałeś, że będzie 'A'
  17.  
  18. $b->property = 'B'
  19. print $b->property; // B, teraz jest dobrze. Ustawiasz $this->property osobno dla A i B


Tak to wygląda. Jest jeszcze możliwość użycia statycznych atrybutów klasy, ale z tym odsyłam do manuala
thek
Klasa B dziedziczy schemat klasy rodzicielskiej czyli nazwy i ciała funkcji (za wyjątkiem specjalnych jak choćby konstruktor)oraz parametrów, ale nie przypisane wartości do już istniejących obiektów. By móc w każdym elemencie klasy odnosić się do pewnego pola, które jest wspólne dla wszystkich musisz zadeklarować dany argument jako static. Pamiętaj jednak, że każdy z obiektów ma do niej dostęp i zmiana w jednym z nich powoduje, że jej wartość jest zmieniona dla wszystkich. A to może być efekt na jakim Ci nie zależy. By zrobić to o czym myślisz, musiałbyś przewidzieć możliwość przypisania obiektu klasy rodzica obiektowi klasy pochodnej.
  1. $a = new A;
  2. //tu coś robimy z danymi obiektu klasy A
  3. $b = new B($a)
Sprowadzi się to do inicjalizacji klasy pochodnej obiektem klasy rodzica. Myślę, że odpowiedni konstruktor w klasie B tu wystarczyłby. Musiałbyś sprawdzić czy obiekt jest klasy przodka i jego danymi uzupełnić odpowiednie atrybuty.

EDIT: By wyjaśnić Ci bezsensowność Twojego myślenia weź pod uwagę, że klasa może utworzyć wiele obiektów...
  1. $a1 = new A;
  2. $a2 = new A;
  3. $a3 = new A;
  4. $b = new B;
Pytanie teraz... Skąd wiedziałbyś czy w b są dane obiektu a1, a2 czy a3? Losowe, ostatniego, pierwszego?
phpion
Cytat(thek @ 13.10.2009, 15:29:29 ) *
Klasa B dziedziczy schemat klasy rodzicielskiej czyli nazwy i ciała funkcji (za wyjątkiem specjalnych jak choćby konstruktor)

Czy przypadkiem konstruktory również nie są dziedziczone?
Crozin
O ile nie są uczynione prywatnymi to są.
phpion
Cytat(Crozin @ 14.10.2009, 15:24:30 ) *
O ile nie są uczynione prywatnymi to są.

Śmiem twierdzić, że się mylisz.
  1. class A {
  2. private function __construct() {
  3. echo 'Tworze sie!';
  4. }
  5. }
  6.  
  7. class B extends A {
  8. public static function instance() {
  9. return new B();
  10. }
  11. }
  12.  
  13. $obj = B::instance();
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.