RE: Magic Methods not working

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux