> -----Original Message----- > From: Paul M Foster [mailto:paulf@xxxxxxxxxxxxxxxxx] > Sent: Tuesday, January 26, 2010 7:05 PM > To: php-general@xxxxxxxxxxxxx > Subject: Magic Methods not working > > I have a class which instantiates other classes, and has a > magic method > like this: > > function _get($classname) > { > return $this->instantiate($classname); > } > > Obviously, the class also has an instantiate method which does what it > says. > > Here's the problem: When I call the instantiate method, it works fine, > like this: > > $db = $sc->instantiate('database'); > > But when I do the following, it *doesn't* work: > > $db = $sc->database; > > In fact it does not call the instantiate() method; I've placed a print > statement in the instantiate() method which fires at then end of the > routine. That statement doesn't fire with the above code. > > The docs on magic methods are pretty slim, so I'm not sure what it is > I'm missing. Can someone enlighten me? > > Paul http://us2.php.net/manual/en/language.oop5.magic.php There are TWO underscores needed, not one. __get() Also, just to save you some time/grief, you might consider using my awesome routines: Put these in your base.class.php and extend it for all other classes. Magic. /** * Provides generic getters and setters * * @access public * @param string $method The method name. * @param array $arguments The arguments passed to the method. * @return mixed * @author Daevid Vincent [daevid@xxxxxxxxxx] * @date 02/02/09 * @see __get(), __set() */ public function __call( $method, $arguments ) { $prefix = strtolower( substr( $method, 0, 3 ) ); $property = strtolower( substr( $method, 4 ) ); if ( empty($prefix) || empty($property) ) return; //exit("__call($method) :: prefix='$prefix' and property='$property'"); if ( 'get' == $prefix ) { if ( property_exists($this, $property) ) return $this->$property; else return $this->__get($property); } elseif ( 'set' == $prefix ) { if ( property_exists($this, $property) ) return $this->$property = $arguments[0]; else return $this->__set($property, $arguments[0]); } // Technically we should never get to this point as most calls are get_() or set_() echo "<p><font color='#ff0000'>Attempted to '".$prefix."->".$method."()' in class '".$this->get_class_name()."'.</font><p>\n"; backtrace(); } /** * magic function to handle any accessing of undefined variables. * Since PHP is "lax" this will help prevent stupid mistakes. * * @access public * @return void * @param mixed $property name of the variable * @author Daevid Vincent [daevid@xxxxxxxxxx] * @date 05/14/09 * @see __set(), __call() */ public function __get($property) { if ($_SESSION['DEVELOPMENT'] && !$_SESSION['mobile']) { echo "<p><font color='#ff0000'>Attempted to __get() non-existant property/variable '".$property."' in class '".$this->get_class_name()."'.</font><p>\n"; $this->suggest_alternative($property); backtrace(); exit; } else exit("__get($property) NO SUCH PROPERTY IN ".$this->get_class_name().' CLASS'); //Throw new BadProperty($this, 'get', $property); } /** * magic function to handle any setting of undefined variables. * Since PHP is "lax" this will help prevent stupid mistakes. * * @access public * @return void * @param mixed $property name of the variable * @param mixed $val value of the variable * @author Daevid Vincent [daevid@xxxxxxxxxx] * @date 05/14/09 * @see __get(), __call() */ public function __set($property, $val) { if ($_SESSION['DEVELOPMENT'] && !$_SESSION['mobile']) { echo "<p><font color='#ff0000'>Attempted to __set() non-existant property/variable '".$property."' to '".$val."' in class '".$this->get_class_name()."'.</font><p>\n"; $this->suggest_alternative($property); backtrace(); exit; } else exit("__set($property) NO SUCH PROPERTY IN ".$this->get_class_name().' CLASS'); //Throw new BadProperty($this, 'set', $property); } /** * Suggests alternative properties should a __get() or __set() fail * * @param string $property * @return string * @author Daevid Vincent [daevid@xxxxxxxxxx] * @date 05/19/09 * @see __get(), __set(), __call() */ public function suggest_alternative($property) { $parts = explode('_',$property); foreach($parts as $i => $p) if ( in_array($p, array('_','id','get','set')) ) unset($parts[$i]); echo 'checking for <b>'.implode(' or ',$parts)."</b> and suggesting the following:<br/>\n"; foreach($this as $key => $value) foreach($parts as $p) if (stripos($key, $p) !== false) { if ($property == 'get_'.$p || $property == 'set_'.$p) $possibilities[] = '<li>'.$key."<b>()</b> <i>note the parenthesis</i></li>"; else $possibilities[] = '<li>'.$key."</li>"; } echo "<ul>\n".implode("\n",array_unique($possibilities))."</ul>\n"; //[dv] unfortunately there doesn't seem to be a way to know if someone called this as a method () or directly :( //if ( strpos($property, '()') === false ) if (count($parts) == 1 && $property == 'get_'.$parts[0] || $property == 'set_'.$parts[0]) echo 'Perhaps you forgot the parenthesis at the end of the method call, and meant this instead: <b>'.$property.'()</b>'; } -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php