Can I dynamically set my class properties?

Rather than write a huge list of properties used by a class I want to know if I can dynamically generate them when needed. I have looked and __set and __get but I am not sure how (or if) I use them with what I am trying to do.

The function I have at the moment is this (obviously doesn’t work):

public function getShowHelpingDetails($id) {                
$this->show_id = $id;        
$result = $this->selectRecord($this->table, $this->show_id, '*', '', 'show_');       
foreach ($result as $key => $value) {            
  $this->{$key} = $value;       
}            
}

And then trying to access the properties like this:

$h = new ShowHelping;
     $helping = $h->getShowHelpingDetails($show_id);
echo $helping->time;

Can anyone help me with this and if not possible advise of a better way to set my class properties without huge lists of them?

Take a look at http://www.sitepoint.com/forums/showthread.php?869163-Curious-Magic-Issue-(I-think)

ServerStorm utilized something very similar, and it had the ability to validate the property names in each class so you couldn’t just add new ones (kind of an added protection).

Thank you - I am reading through the thread now to see if I can get my head around it :slight_smile:

I am needing some more help as I have tried to use the information from that thread and apply it to my requirements but it still isn’t working and I am not sure I have done it correctly.

In my database class (as all classes extend it) I have put the following:

protected $properties = array();
    protected $allowed_props = array();

function __set($property, $value) {            
try {          
if(in_array($property, $this->allowed_props)) {              
$this->properties[$property] = $value;        
} 
else {           
 throw new CustomException("The $property is not allowed");        
}    
} catch (CustomException $e) {        
echo $e->getErrorReport();    
}     
 }    
// get defined property 
 function &__get($property) {        
return $this->properties[$property];        
}

  protected function getAllProperities() {        
return $this->properties;        
}

Then in my child class I have this (I haven’t changed the original function):

public function __construct() {                
parent::__construct(DB_SERVER, DB_USER, DB_PASS, DB_NAME);                
$this->allowed_props = array('id','show_id','help_text');    
}
public function getShowHelpingDetails($id) {                
$this->show_id = $id;        
$result = $this->selectRecord($this->table, $this->show_id, '*', '', 'show_');        
foreach ($result as $key => $value) {           
$this->$key = $value;        
}            
}

Edit: I forgot to say, I am just receiving the error ‘The $property is not allowed’ ($property shows the variable name)

Thanks to a response on another forum I now have this solved by adding a return from my function so the end function that worked (using the previous set and get code) is:

public function getShowHelpingDetails($id) {                
$this->show_id = $id;        
$result = $this->selectRecord($this->table, $this->show_id, '*', '', 'show_');        
foreach ($result as $key => $value) {           
$this->{$key} = $value;        
}  
return $this;          
} 

class TestObject {}

$t = new TestObject;
$t->newProp = "cat";

print $t->newProp;

Works, creates a public property.

Now for your current code, your try catch is all wrong you do not throw an exception with in a try block nor do you hand the error directly in your object that is throwing the exception.


class TestObject
{
  protected
    $properties    = array(),
    $allowed_props = array();

  function __set ( $property, $value )
  {
    $property = strtolower( $property );

    if ( in_array( $property, $this->allowed_props ) ) {
      $this->properties[ $property ] = $value;
      return $this;
    }
    
    throw new CustomException("The $property is not allowed.");
  }

  function __get ( $property ) {
    return $this->properties[ strtolower( $property ) ]; }
}