Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP5] Monitoring obiektu w php
Forum PHP.pl > Inne > Oceny
hwao
Ostatnio zastanawiałem się jak można pomierzyć, posprawdzać niektóre fragmenty aplikacji, wpadłem na pomysł zasotosowania metod __call(), __get(), __set() i całośc wyglada tak:

  1. <?php
  2. /**
  3.  * Monitor
  4.  * 
  5.  * @author Paweł `hwao` Halicki
  6.  * @version 1.0.0
  7.  */
  8. class Monitor {
  9. /**
  10.  * Obiekt do monitorowania
  11.  *
  12.  * @var Object
  13.  */
  14. private  $oObject = null;
  15. /**
  16.  * Nazwa monitorowanego obiektu
  17.  *
  18.  * @var string
  19.  */
  20. protected $sObject = null;
  21.  
  22. /**
  23.  * Konstruktor
  24.  *
  25.  * @param Object $oObject
  26.  */
  27. public function __construct( $oObject ) {
  28. $this->oObject = $oObject;
  29. $this->sObject = get_class( $oObject );
  30. }
  31.  
  32. /**
  33.  * Handler pobierania właściwości
  34.  *
  35.  * @param string $sKey
  36.  * @return mixed
  37.  */
  38. public function __get( $sKey ) {
  39. return $this->oObject->$sKey;
  40. }
  41.  
  42. /**
  43.  * Handler do przypisywania wartości właściwości
  44.  *
  45.  * @param string $sKey
  46.  * @param mixed $mVal
  47.  * @return mixed
  48.  */
  49. public function __set( $sKey, $mVal ) {
  50. return $this->oObject->$sKey = $mVal;
  51. }
  52.  
  53. /**
  54.  * Handler to obsługi metod
  55.  *
  56.  * @param string $sMethod
  57.  * @param array $aArgs
  58.  * @return mixed
  59.  */
  60. public function __call( $sMethod, $aArgs ) {
  61. switch( count( $aArgs ) ) {
  62. case 1:
  63. return $this->oObject->$sMethod( $aArgs[0] );
  64. break;
  65. case 2:
  66. return $this->oObject->$sMethod( $aArgs[0], $aArgs[1] );
  67. break;
  68. default:
  69. case 0:
  70. return $this->oObject->$sMethod();
  71. break;
  72. }
  73. return false;
  74. }
  75. }
  76. ?>


Na razie nic wielkiego, dajmy jakąś klasa do prze testowania np.:
  1. <?php
  2. /**
  3.  * Human
  4.  * 
  5.  * Testowa klasa, oczywiscie można uzyć każdej innej dowolnej
  6.  *
  7.  */
  8. class Human {
  9. /**
  10.  * Imię
  11.  *
  12.  * @var string
  13.  */
  14. private $sFirstName = '';
  15. /**
  16.  * Nazwisko
  17.  *
  18.  * @var string
  19.  */
  20. private $sSurname = '';
  21. /**
  22.  * Nick/ksywa
  23.  *
  24.  * @var string
  25.  */
  26. public $sNick = '';
  27. /**
  28.  * Czy żyje
  29.  *
  30.  * @var boolen
  31.  */
  32. protected $bAlive = null;
  33.  
  34. /**
  35.  * Konstruktor
  36.  *
  37.  */
  38. public function __construct() {
  39. $this->bAlive = false;
  40. }
  41.  
  42. /**
  43.  * Narodziny
  44.  *
  45.  * @param string $sFirstName
  46.  * @param string $sSurname
  47.  */
  48. public function Born( $sFirstName, $sSurname ) {
  49. if( $this->bAlive == false ) {
  50. $this->bAlive  = true;
  51. $this->sFirstName = $sFirstName;
  52. $this->sSurname  = $sSurname;
  53. }
  54. else {
  55. throw new Exception( 'Object already live!' );
  56. }
  57. }
  58.  
  59. /**
  60.  * Ustawienie "czasu" życia
  61.  * 
  62.  * @param integer $iLive
  63.  * @return boolen
  64.  */
  65.  
  66. public function setLiveTime( $iLive ) {
  67. return true;
  68. }
  69.  
  70. /**
  71.  * tongue.gif
  72.  * 
  73.  * @return boolen
  74.  */
  75. public function goToHell() { // :)
  76. $this->bAlive = false; 
  77. return true;
  78. }
  79. }
  80. ?>


Nie spierajmy sie o sama budowę klasy, to tylko przykład smile.gif

Robimy coś takiego:
  1. <?php
  2. $Human = new Monitor( new Human() );
  3. $Human->Born( 'Paweł', 'Halicki' );
  4. $Human->setLiveTime( 100 );
  5. $Human->sNick = 'hwao';
  6. $Human->setLiveTime( 50 );
  7. $Human->sNick = 'jedi hwao';
  8. $Human->setLiveTime( 0 );
  9. $Human->goToHell();
  10. $Human->sNick = 'sith hwao';
  11. ?>


Wszytko działa, tak jakbyśmy operowali na obiekcie Human, ale tak naprawdę wszystkie operacje wykonywane są na obiekcie Monitor. W praktyce oznacza to że zanim cos trafi do instancji klasy Human zostaje przeanalizowane przez obiekt Monitor. Daje nam to sporo możliwość, rozbudujmy klasę Monitor w taki oto sposób:
  1. <?php
  2. /**
  3.  * Rozszerzenie Monitora
  4.  * 
  5.  * @author hwao
  6.  * @version 1.0.0
  7.  */
  8. class ProMonitor extends Monitor {
  9. /**
  10.  * Konstuktor
  11.  *
  12.  * @param Object $oObject
  13.  */
  14. public function __construct( $oObject ) {
  15. parent::__construct( $oObject );
  16. echo 'Create new instance of object "'.$this->sObject.'"'."\n";
  17. }
  18.  
  19. /**
  20.  * Handler pobierania właściwości
  21.  *
  22.  * @param string $sKey
  23.  * @return mixed
  24.  */
  25. public function __get( $sKey ) {
  26. echo 'return '.$this->sObject.'::'.$sKey."\n";
  27. return parent::__get( $sKey );
  28. }
  29.  
  30. /**
  31.  * Handler do przypisywania wartości właściwości
  32.  *
  33.  * @param string $sKey
  34.  * @param mixed $mVal
  35.  * @return mixed
  36.  */
  37. public function __set( $sKey, $mVal ) {
  38. echo $this->sObject.'::'.$sKey.' = '.$this->____getType( $mVal )."\n";
  39. return parent::__set( $sKey, $mVal );
  40. }
  41.  
  42. /**
  43.  * Handler to obsługi metod
  44.  *
  45.  * @param string $sMethod
  46.  * @param array $aArgs
  47.  * @return mixed
  48.  */
  49. public function __call( $sMethod, $aArgs ) {
  50. $aArgs = array_map( array( $this, '____getType' ), $aArgs );
  51. echo $this->sObject.'::'.$sMethod.'( '.join( ', ', $aArgs ).' );'."\n";
  52. return parent::__call( $sMethod, $aArgs );
  53. }
  54.  
  55. /**
  56.  * Zdobywanie wiadomości o zmiennej
  57.  * 
  58.  * Pobieranie jej typu i możliwie przydatnych informacji
  59.  *
  60.  * @param mixed $mVal
  61.  * @return string
  62.  */
  63. protected function ____getType( $mVal ) {
  64. switch( strtolower( gettype( $mVal ) ) ) {
  65. case 'boolean':
  66. return '(boolean)'.( $mVal==true ? 'true' : 'false' );
  67. break;
  68. case 'integer':
  69. return '(integer)'.$mVal;
  70. break;
  71. case 'double':
  72. return '(double)'.$mVal;
  73. break;
  74. case 'string':
  75. return '(string)''.$mVal.'''; //'(length='.strlen($mVal).')';
  76. break;
  77. case 'array':
  78. return '(array)'.$mVal.'(count='.count($mVal).')';
  79. break;
  80. case 'object':
  81. return '(object)'.$mVal.'(name='.get_class($mVal).')';
  82. break;
  83. case 'resource':
  84. return '(resource)'.$mVal.'(type='.get_resource_type($mVal).')';
  85. break;
  86. case 'null':
  87. return '(null)Null';
  88. break;
  89. default:
  90. return '(unknown)'.$mVal;
  91. break;
  92. }
  93.  
  94. }
  95. }
  96. ?>


Trochę zostało dodane, głównie wyświetlanie informacji co i jak się dzieje sprawdzamy co się stanie po uruchomieniu takiego kodu:
  1. <?php
  2. /**
  3.  * Prosty sposób użycia
  4.  */
  5. echo '<pre>';
  6. $Human = new ProMonitor( new Human() );
  7. $Human->Born( 'Paweł', 'Halicki' );
  8. $Human->setLiveTime( 100 );
  9. $Human->sNick = 'hwao';
  10. $Human->setLiveTime( 50 );
  11. $Human->sNick = 'jedi hwao';
  12. $Human->setLiveTime( 0 );
  13. $Human->goToHell();
  14. $Human->sNick = 'sith hwao';
  15. echo '</pre>';
  16. ?>


Po wykonaniu skryptu naszym oczom ukaże się co się działo z obiektem Human:
Kod
Create new instance of object "Human"
Human::Born( (string)'Paweł', (string)'Halicki' );
Human::setLiveTime( (integer)100 );
Human::sNick = (string)'hwao'
Human::setLiveTime( (integer)50 );
Human::sNick = (string)'jedi hwao'
Human::setLiveTime( (integer)0 );
Human::goToHell(  );
Human::sNick = (string)'sith hwao'


W przykładzie widać tylko wejście ale nic nie stoi na przeszkodzie żeby dodać inne rzeczy, np.:
- czas dostępu do metod/właściwości (jak długo co się wykonuje),
- co zwraca dane metoda/właściwości.

Wszelkie pytania mile widziane, wiem że nie jest to za bardzo zaawansowane, ale komuś może się przydać.

Kod jest fragmentem framework'a.

Pozdrawiam
bela
hwao, na phpedii jest opisany obserwator. Może zainteresujesz się ;]
Strzałek
Bardzo ciekawe zastosowanie magicznych metod.

Mi się to podoba.
NetJaro
Dzięki temu zrozumiałem działanie __set(), __get() i __call() - hwao dzięki smile.gif
LBO
hmm.. nie jestem pewien ale chyba w repozytorium PEAR'a maja cos podobnego.. chodzi o monitorowanie obiektu, a nie sposob jaki zostal podany wyzej
hwao
Cytat(LBO @ 2006-03-05 00:45:02)
hmm.. nie jestem pewien ale chyba w repozytorium PEAR'a maja cos podobnego.. chodzi o monitorowanie obiektu, a nie sposob jaki zostal podany wyzej

Co rozumiesz przez monitorowanie obiektu, dla mnie jest to zobaczenie jak obiekt oddzialowywuje ze srodowiskiem jakie go otacza.
Vomit
Ale po co to robic? Ma to jakis cel? rolleyes.gif
Vengeance
"Ma to jakis cel? "

Jeden woli robić var_dumpy, drugi unit testy, a trzeci skorzysta z metody hwao. Nic nigdy się nie zmarnuje.
hwao
Cytat(Vomit @ 2006-03-05 12:01:40)
Ale po co to robic? Ma to jakis cel? rolleyes.gif

Ma, ma, latwo mozna sprawdzic co sie dzieje w obiekcie, przydatne przy szukaniu bledu.

Ale glownie pisze to poto zeby pomierzyc czasy wykonywania poszczegolnych metod.

Przyklad tez pokazuje jak uzywac w php5 magicznych metod, dzieki czemu mozna napisac np DBObject, moge pokazac kod jak ktos chce.
Vengeance
"pomierzyc czasy wykonywania poszczegolnych metod"

Zend Studio Client/Server + Debug ? I nie ma mocnych ;]
hwao
Cytat(Vengeance @ 2006-03-05 14:50:34)
"pomierzyc czasy wykonywania poszczegolnych metod"

Zend Studio Client/Server + Debug ? I nie ma mocnych ;]

i nie dziala, przynajmniej mi...

pozatym koszty;)
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.