Can't figure it out how it works...

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
dwnthk
Forum Newbie
Posts: 13
Joined: Mon Oct 08, 2007 5:55 am

Can't figure it out how it works...

Post by dwnthk »

Hi there,

I am reading a book on PHP. There is the example codes in the book:

Code: Select all

<?php

abstract class PropertyObject implements Validator {
   protected $propertyTable = array();
   protected $data;
   ....
   function __construct($arData) { 
      $this->data = $arData;
   } 
   function __get($propertyName) {
      ...
   }

   function __set($propertyName, $value) { 
      ...
      if (method_exists($this, 'set'. $propertyName)) {
           return call_user_func(array($this, 'set' . $propertyName), $value);
      } else ...
      ...
   }
}

?>
In the other script:

Code: Select all

<?php
...
class Address extends PropertyObject {
   
    function __construct($arData) {
       parent::__construct($arData);
       $this->propertyTable['address']='addressid';
       $this->propertyTable['state']='cstate';
       ...
    }
 
    function validate() {
       if(strlen($this->state) !=2 ) { ... }     // Where does $this->state come from?
       ...
       if (!$this->address) { ... }    // Again, where does $this->address come from?
       ...
    }

}
?>
In the above codes, the class Address has no properties declared. I am not sure where the $this->state and $this->address come from?

And the double underscore (__set and __get) does have some real functionalities in the programming or it is just a way the PHP programmers will do? If I use "_set" or "set" instead of "__set" will change the program?

Thanks.

Dave
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

__get and __set, like __construct (and several other methods) are called magic methods. They are not invoked directly by you (normally) but rather automatically by PHP. In this particular case, the properties "state" and "address" are requested by the second snippet. Since they are requested, the __get method will be called. I will assume that the removed code from the first snippet would access the "propertyTable" property of PropertyObject to find those values.
dwnthk
Forum Newbie
Posts: 13
Joined: Mon Oct 08, 2007 5:55 am

Post by dwnthk »

Code: Select all

<?php
require_once('Validator.php');
abstract class PropertyObject implements Validator {
   
   protected $propertyTable = array();
   protected $changedProperties = array();
   protected $data;
   protected $errors = array();

   public function __construct($arData) {
      $this->data = $arData;
   }   // function __construct()

   function __get($propertyName) {
      if (!array_key_exists($propertyName, $this->propertyTable))
          throw new Exception ("Invalid property \"$propertyName\"!"); 
      if (method_exists($this, 'get' . $propertyName))  {
         return call_user_func(array($this, 'get'.$propertyName));       // never run this code?
      } else {
         return $this->data[$this->propertyTable[$propertyName]];
      }   // if method_exists      
   }   // function __get()

    function __set($propertyName, $value) {
      if (!array_key_exists($propertyName, $this->propertyTable))
          throw new Exception ("Invalid property \"$propertyName\"!");
      if (method_exists($this, 'set' . $propertyName)) {
          return call_user_func( array($this, 'set' . $propertyName), $value);      // never run this code?
       } else {
          ....
       }
    }   // function __set()

}  // class PropertyObject
It is more or less the complete code of the PropertyTable class (hope I am not against the copyright right here now :lol: ).

The code "call_user_func(...)" would never be run in this PropertyTable class right? There isn't any 'set'.$propertyName in this class. Is it for the subclasses?

In the subclass Address class which extends from PropertyTable:

Code: Select all

<?php
require_once('PropertyTable.php');
class Address extends PropertyObject {

   function __construct($addressid) {
      $arData = DataManager::getAddressData($addressid);   // static function to get data from database
      parent::__construct($arData);
      $this->propertyTable['addressid'] = 'addressid';
      $this->propertyTable['address1'] = 'address1';
      $this->propertyTable['address2'] = 'address2';
      $this->propertyTable['state'] = 'state';
   }  // function __construct()

   function validate() {
      if (strlen($this->state) !=2 ) {                             // where is $this->state come from?
         $this->errors['state'] = 'Please choose a valid state.';
      }
      ....
    }    // function validate()
}   // class Address
I can't figure out where is the $this->state coming from?
And the __construct() would be called when we 'new' a object. When the __get and __set would be called automatically?

Sorry... it is a bit long for read :?

Dave
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

dwnthk wrote:The code "call_user_func(...)" would never be run in this PropertyTable class right? There isn't any 'set'.$propertyName in this class. Is it for the subclasses?
They are intended for subclasses. Since PropertyObject is an abstract class you can't actually have an instance of it (directly.)
dwnthk wrote:I can't figure out where is the $this->state coming from?
What do you mean? It's used to call the __get method.
dwnthk wrote:And the __construct() would be called when we 'new' a object. When the __get and __set would be called automatically?
All three are called automatically for you based on your actions; __construct for new foo, __get for $foo->bar, __set for $foo->bar = 2.
Post Reply