Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP5 OOP] Użycie metody __set dla składowej jako tablicy
Forum PHP.pl > Forum > PHP > Object-oriented programming
phpion
Hej!
Mam pewien problem. W jaki sposób wykonać metodę __set($param, $value) dla składowej klasy będącej tablicą? Może podam na przykładzie:
  1. <?php
  2. class SomeClass {
  3. private $array = array(
  4. 'field' => 'value'
  5. );
  6.  
  7. public function __set($param, $value) {
  8. $this->$param = $value;
  9. }
  10. }
  11.  
  12. $obj = new SomeClass();
  13. echo "<pre>".print_r($obj, true)."</pre>";
  14.  
  15. $obj->__set("array['field']", "change");
  16. echo "<pre>".print_r($obj, true)."</pre>";
  17. ?>

Co w rezultacie daje:
  1. SomeClass Object
  2. (
  3. [array:private] => Array
  4. (
  5. [field] => value
  6. )
  7.  
  8. )
  9. SomeClass Object
  10. (
  11. [array:private] => Array
  12. (
  13. [field] => value
  14. )
  15.  
  16. [array['field']] => change
  17. )

W jaki sposób zmienić wartość $this->array['field']?

PS: wiem, że można to zrobić tworząc osobną metodę zmieniającą element tablicy ale czy da się to samo osiągnąć korzystając z __set()?
Sedziwoj
  1. <?php
  2. $obj = new SomeClass();
  3. $obj->array = array('zastapi' => 'ss');
  4. ?>
phpion
Wow, aż się dziwię, że można modyfikować wartość składowej będącej prywatną :| No ale dzięki.
Hmm, w sumie nie działa do końca jak powinno bo przypisuje składowej nową tablicę, a mi chodziło o zmianę wartości dla jednego indeksu. Mając w $this->array kilka elementów tracimy je.
Ludvik
  1. <?php
  2. class SomeClass {
  3. private $array = array(
  4. 'field' => 'value'
  5. );
  6.  
  7. public function __set($param, $value) {
  8. $this->array[$param] = $value;
  9. }
  10. }
  11. ?>
phpion
Heh, chyba sie nie do końca zrozumieliśmy. To, że w ten sposób można to wiem ale przy takiej postaci __set() nie będzie można ustawić parametrów, które nie są $this->array. Jeżeli będę miał składową np. private skladowa; to wywołanie __set() w postaci przedstawionej przez Ciebie będzie ustawiało $this->array['skladowa'] zamiast $this->skladowa.
Ludvik
Nie zrobisz 2 rzeczy na raz... Albo ograniczasz się do tablicy, albo robisz tak jak napisał Sedziwoj. Ewentualnie możesz dopisać gettera i zrobić coś w stylu:

  1. <?php
  2. $obj->array = array_merge($obj->array, array('klucz' => 'wartosc'));
  3. ?>
phpion
No właśnie o to mi chodziło czy można to machnąć w jednej metodzie (bez warunków po nazwie składowej).
Sedziwoj
Cytat(Ludvik @ 2.06.2007, 14:50:54 ) *
Nie zrobisz 2 rzeczy na raz...


A zrobisz, bo jeśli dobrze pamiętam $this->cos, szuka najpierw właściwości klasy o tej nazwie jak nie znajduje odpala __get() więc można odwołać się i $this->array['cos'] jak i $this->cos gdy
  1. <?php
  2. ...
  3. public function __get( $param ){
  4.  return $this->array[$param];
  5. }
  6. ...
  7. ?>
Ludvik
Raczej nie o to chodziło. Po pierwsze $this->array['cos'] nie zadziała, bo tablica jest prywatna. Nawet jeżeli przeciążysz __get, to żeby dostać się do tablicy w ten sposób musisz zapisać go tak:
  1. <?php
  2. public function __get($var) {
  3.  return $this->$var;
  4. }
  5. ?>

Jeżeli chcesz odwołać się do elementu z tablicy poprzez $this->cos, to wtedy przeciążasz funkcję tak:
  1. <?php
  2. public function __get($var) {
  3. return $this->array[$var];
  4.  }
  5. ?>

Ale wtedy nie odwołasz się do atrybutów obiektu. Jeżeli spróbujesz zrobić coś takiego:
  1. <?php
  2. class SomeClass {
  3. protected $array = array();
  4.  
  5. public function __set($var, $val) {
  6. $this->$var = $val;
  7. }
  8.  
  9. public function __get($var) {
  10. return $this->$var;
  11. }
  12. }
  13.  
  14. $obj = new SomeClass();
  15. $obj->array['xxx'] = 'yyy';
  16. ?>

To wywali:
Kod
Notice: Indirect modification of overloaded property SomeClass::$array has no effect

Jeżeli przeciążysz __set inaczej, to nie wydostaniesz się poza tablicę.

Dyskusja wyglądałaby trochę inaczej, gdyby nie ten modyfikator przy tablicy...
Sedziwoj
Cytat(Ludvik @ 3.06.2007, 00:05:32 ) *
Raczej nie o to chodziło. Po pierwsze $this->array['cos'] nie zadziała, bo tablica jest prywatna.


Przecież $this używasz tylko w obiekcie, więc to że jest prywatna akurat nie ma nic do znaczenia.
Ech nie chce mi się pisać...
  1. <?php
  2. class SomeClass {
  3. private $array = array();
  4.  
  5. public function __set($var, $val) {
  6. $this->array[$var] = $val;
  7. }
  8.  
  9. public function __get($var) {
  10. return $this->array[$var];
  11. }
  12. public function cos( $var ){
  13.  echo $this->array[$var];//jedne sposób dostania, bezpośredni
  14.  echo $this->$var;//drugi, pośredni przez __get()
  15. }
  16. }
  17.  
  18. $obj = new SomeClass();
  19. $obj->xxx = 'yyy<br />';
  20. echo $obj->xxx;
  21. $obj->cos( 'xxx' );
  22. ?>


EDIT: głupia kontrola danych (i zmiana) jest na tej stronie
Ludvik
Cytat
Przecież $this używasz tylko w obiekcie, więc to że jest prywatna akurat nie ma nic do znaczenia.

Nie doczytałem, trochę późno jest jak dla mnie tongue.gif

Cytat
Heh, chyba sie nie do końca zrozumieliśmy. To, że w ten sposób można to wiem ale przy takiej postaci __set() nie będzie można ustawić parametrów, które nie są $this->array. Jeżeli będę miał składową np. private skladowa; to wywołanie __set() w postaci przedstawionej przez Ciebie będzie ustawiało $this->array['skladowa'] zamiast $this->skladowa.

Tutaj jest problem. phpion.com chciał mieć możliwość jednoczesnego operowania i na tablicy array i na zwykłych atrybutach obiektu. W ten sposób, niestety, nie uda się tego zrobić...

EDIT: Powiedzmy, że udało mi się to zrobić tak:
  1. <?php
  2. class SomeClass {
  3. private $array = array();
  4.  
  5. private $skladowa = 0;
  6.  
  7. public function __set($var, $val) {
  8. if (isset($this->$var)) {
  9. $this->$var = $val;
  10. } else {
  11. $this->array[$var] = $val;
  12. }
  13. }
  14.  
  15. public function __get($var) {
  16. if (isset($this->$var)) {
  17. return $this->$var;
  18. } else {
  19. return $this->array[$var];
  20. }
  21. }
  22. }
  23.  
  24. $obj = new SomeClass();
  25.  
  26. $obj->skladowa = 1;
  27. $obj->nieskladowa = 'xxx';
  28. ?>
Sedziwoj
Cytat(Ludvik @ 3.06.2007, 00:41:38 ) *
Nie doczytałem, trochę późno jest jak dla mnie tongue.gif
Tutaj jest problem. phpion.com chciał mieć możliwość jednoczesnego operowania i na tablicy array i na zwykłych atrybutach obiektu. W ten sposób, niestety, nie uda się tego zrobić...

Czyli $obj->xxx i $obj->array['xxx']?
  1. <?php
  2. class SomeClass {
  3. public $array = array();
  4.  
  5. public function __set($var, $val) {
  6. $this->array[$var] = $val;
  7. }
  8.  
  9. public function __get($var) {
  10. return $this->array[$var];
  11. }
  12. public function cos( $var ){
  13.  echo $this->array[$var];
  14.  echo $this->$var;
  15. }
  16. }
  17.  
  18. $obj = new SomeClass();
  19. $obj->xxx = "yyy<br />n";
  20. echo $obj->xxx;
  21. $obj->cos( 'xxx' );
  22. echo $obj->array['xxx'];
  23. ?>


Tylko jaki jest sens tego?
devnul
sugeruje użyć ArrayAcces i będzie po problemie
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.