Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Problem z magicznymi metodami
Forum PHP.pl > Forum > Przedszkole
fesseme
Mam pewien problem z magiczną metodą __get(), pokażę przykładowy kod i opiszę jaki mam problem.
  1. class DANE{
  2. public function __get($name){
  3. if (is_null($this->{$name}))
  4. $this->{$name}();
  5.  
  6. return $this->{$name};
  7. }
  8.  
  9. private $zmienna;
  10. private function zmienna(){
  11. $this->zmienna = 'jakies dane';
  12. }
  13.  
  14. private $zmienna2;
  15. private function zmienna2(){
  16. $this->zmienna2 = $this->zmienna . ' dodatek do danych';
  17. }
  18. }

Problem powstaje gdy chcę użyć metody __get() dla zmienna2.
Dostaję tylko napis ' dodatek do danych', czy ktoś mógłby mi wytłumaczyć dlaczego nie 'jakies dane dodatek do danych'.
Ominąłem to na chłopski rozum dając if(is_null()), ale za każdym razem tak robiąc to można dostać hopla.
Z góry dziękuję za odpowiedź.
JoShiMa
Cytat(fesseme @ 24.02.2011, 23:31:07 ) *
Problem powstaje gdy chcę użyć metody __get() dla zmienna2.
Dostaję tylko napis ' dodatek do danych', czy ktoś mógłby mi wytłumaczyć dlaczego nie 'jakies dane dodatek do danych'.
Ominąłem to na chłopski rozum dając if(is_null()), ale za każdym razem tak robiąc to można dostać hopla.
Z góry dziękuję za odpowiedź.

A nie wydaje Ci się, że musisz najpierw wywołać metodę private function zmienna(), żeby nadać wartość parametrowi $zmienna? To nie z __get() jest problem, tylko z Twoim pojmowaniem obiektów tongue.gif
fesseme
ale w funkcji __get chcę wywołać tą metodę w linii 4.
Czy to oznacza że magiczne metody get nie mogę wywołać wew. funkcji?
thek
To zrób tak:
  1. $cos = new DANE();
  2. var_dump( $cos );
To czego Ci brakuje to konstruktor nadający wartości domyślne określonym atrybutom. Na razie bowiem tworzysz zmienną klasy DANE, ale wartości $this->zmienna i $this->zmienna2 są w nich wartościami pustymi i stąd takie zachowanie. Wywołujesz bowiem metodę zmienna2(), ale sięgając do $this->zmienna wewnątrz niej $this->zmienna nie ma wciąż nadanej wartości i kod robi Ci zonka.
Daiquiri
fesseme, możesz wszystko tylko pytanie tylko co chcesz zobaczyć wywołując puste elementy? Skąd mają się te "jakies dane" wziąć?
Crozin
A teraz odpowiedz proszę po co w ogóle angażujesz w to magiczną metodę __get()? Nie możesz zrobić normalnie tego?
  1. class Data {
  2. protected $variableA;
  3.  
  4. public function getVariableA() {
  5. if ($this->variableA === null) {
  6. ...
  7. }
  8.  
  9. return $this->variableA;
  10. }
  11. }
wookieb
Cytat
__get is utilized for reading data from inaccessible properties

Czyli jeżeli próbujesz się dostać do NIEDOSTĘPNYCH wartości. Niedostępnych czyli nie istniejących bądź wartości nie dostępnych z danego kontekstu.
Kod
$this->zmienna

jest dostępna z kontekstu wnętrza twojej klasy, dlatego __get nie jest wywoływane.

Dlatego m.in z tego powodu wiele osób daje właściwościom prywatnym znak _ przed nazwę a dalej postępują tak.
  1. class test {
  2. private $_zmienna;
  3. public function __get($name) {
  4. $name = ltrim($name, '_');
  5. // tutaj dalszy kod
  6. }
  7.  
  8. }
fesseme
@thek
konstruktora nie pisałem w przykładzie bo nie sądziłem iż jest on potrzebny by zobrazować mój problem, w rzeczywistej klasie jest jak najbardziej, jednak nie nadaje on wartości
wszystkim polom ponieważ nie jest to konieczne w tym przypadku

@Daiquiri
Dane zostaną nadane przez funkcję o takiej samej nazwie jak zmienna. Funkcja ta wykona obliczenia i przypisze je do zmiennej.

@Crozin
Na samym początku tak zrobiłem, ale przy 10 takiej funkcji już przestałem mieć chęć pisania takich funkcji, dlatego chciałem skorzystać z metody __get()

@wookieb
To jest wskazówka która może zadziałać, sprawdzę jutro rano napiszę relację.

Bardzo dziękuję za wszystkie posty smile.gif
Crozin
@fesseme: W takim razie napisz co chcesz konkretnie zrobić - opisz swój przypadek. Bo na 99% próbujesz źle to zaprojektować.
fesseme
dzięki metodzie __get('zmienna2') chciałem uzyskać efekt taki że
1) funkcja __get sprawdza czy $zmienna2 jest null jeśli tak wywołuje metodę zmienna2() która robi:
a) pobiera $zmienna1 (w tym przypadku powinna się uruchomić funkcja __get() która sprawdza czy $zmienna1 jest null jeśli tak to uruchamia zmienna1() do nadania wartosci 'zmienna1')
cool.gif do zminnej $zmienna1 dodaję napis 'zmienna2' i zapisuję cały tekst w zmienna2
c) $zmienna2 powinna mieć wartość po tych działaniach 'zmienna1 zmienna2' (natomiast ja mam tylko wartosc 'zmienna2' w podanym kodzie na początku)
d) zwracam $zmienna2

Mam nadzieję że nie poplątałem za bardzo.

Crozin
1. A przykład z prawdziwego życia?
2. Ile razy ma być powtarzany tech "ruch" z przypisaniem cząstkowych wartości poprzedzającym zmiennym?
3. Najprawdopodobniej powinieneś zamiast tworzyć dziesiątki właściwości obiektu zrobić jedną tablicę przechowującą te dane.
fesseme
Udało mi się uzyskać efekt taki jaki chciałem, trochę na okrętkę ale działa biggrin.gif
  1. class TEST {
  2. public function __get($name) {
  3. $name = '_'.$name;
  4. if (!isset($this->$name) && function_exists($this->$name()))
  5. $this->$name ();
  6.  
  7. return $this->{$name};
  8. }
  9.  
  10. private $_zmianna2;
  11. private function _zmianna2(){
  12. $this->_zmianna2 = $this->zmianna1.'zmianna2';
  13. }
  14.  
  15. private $_zmianna1;
  16. private function _zmianna1(){
  17. $this->_zmianna1 = 'zmianna1 ';
  18. }
  19. }

W linii 12 na siłę wywołuję metodę __get(), gdyż jeżeli dam $this->_zmianna1 to nie zadziała sad.gif

Sposób zainspirowany dzięki wookieb - tylko w drugą stronę biggrin.gif

Może uda się zrobić to jakoś inaczej, jeżeli tak to proszę o podpowiedź.

@Crozin
1) Przykład z życia, a dokładniej z matematyki bo ten który tworzę na prawdę jest trochę specyficzny i nie nadaje się na przykład.
Konstruktor inicjuje dwa pola obiektu var1 i var2 jakimiś cyframi.
var3 ma przechowywać sumę tych dwóch cyfr która zostaje obliczona przez funkcję var3()
natomiast var4 przechowuje takie działanie (var1+var2)*var1 oczywiście też obliczany przez funkcję var4()
dlatego chce by funkcja var4() zrobiła coś takiego var3*var1

2) Nie potrafię odpowiedzieć na to pytanie wszystko może wyjść w praniu na tą chwilę mam 2 "zagnieżdżenia"

3)Czy stosując tablicę miałbym jakiś inny plus poza tym że wszystko miałbym w jednym miejscu?
Crozin
Podaj Twój konkretny przypadek - nawet jeżeli miałbyś się rozpisać na dwie strony. Bo teraz to jest trochę tak jakbyś przyszedł do mechanika z niedziałającym samochodem i zamiast powiedzieć co jest nie tak wymyślałbyś mu przykłady. wink.gif

Cytat
3)Czy stosując tablicę miałbym jakiś inny plus poza tym że wszystko miałbym w jednym miejscu?
Zamiast polegać na dynamiczności języka pozwalającej tworzyć potworki pokroju $this->$name () miałbyś normalny, bardziej statyczny kod - dużo czytelniejszy i łatwiejszy w zrozumieniu.
fesseme
@Crozin

W PHP uwielbiam właśnie jego dynamiczność, kiedyś mnie to zgubi ale tworzenie tego typu potworków daje mi pewną stratyfikację smile.gif

Wracając do rzeczy kody nie mogę udostępnić z powodu umowy, ale przeprowadziłem testy wydajności z potworkiem i z funkcją zwracającą wartość
i wyszło że program zwolnił 3 krotnie sad.gif

Natomiast jeżeli chodzi o tablice część danych przeniosę do tablicy, ale nie wszystkie z powodu że miałbym w pewnym miejscu tablicę tablic.

Bardzo dziękuję wszystkim za pomoc i w szczególności tobie Crozin za wyrozumiałość i cierpliwość smile.gif
Crozin
Cytat
Wracając do rzeczy kody nie mogę udostępnić z powodu umowy
Nie musisz podawać kodu - opisz po prostu co konkretnie chcesz osiągnąć. Czemu ma dokładnie służyć ta klasa. Najprawdopodobniej próbujesz rozwiązać problem w zły sposób, który wymusza tworzenie takich "niestandardowych" (tak, to wada w tym przypadku) i niejasnych konstrukcji, należałoby to zaprojektować inaczej - dlatego właśnie pytam jaki jest właściwy problem, a nie analogiczne przykłady ponieważ na ich podstawie ciężko jest zaproponować inne rozwiązanie.

Cytat
ale przeprowadziłem testy wydajności z potworkiem i z funkcją zwracającą wartość i wyszło że program zwolnił 3 krotnie
Nie wiem do końca co testowałeś, ale nawet jeżeli faktycznie różnica w szybkości wykonywania jest aż trzykrotna nie ma to pewnie jakiegoś większego odbicia w całości skryptu. Jeżeli coś wykonuje się w 0.1 sek., a Tobie uda się przyśpieszyć program o 0.00006 sek. to naprawdę wiele się nie zyskuje. Trzeba również pamiętać, że w bardzo nielicznych przypadkach taka mikroptymalizacja ma jakikolwiek sens.

Cytat
[...] że miałbym w pewnym miejscu tablicę tablic.
A co konkretnie jest złego w tablicach wielowymiarowych? Jeżeli jakaś grupa danych jest ze sobą bezpośrednio czy nawet pośrednio powiązana powinna być zebrana w jakąś strukturę - możesz do tego wykorzystać tablice lub obiekty.
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.