> -----Original Message-----
> From: Paul M Foster [mailto:pa...@quillandmouse.com] 
> Sent: Tuesday, January 26, 2010 7:05 PM
> To: php-general@lists.php.net
> Subject: [PHP] 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 [dae...@daevid.com]
* @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 [dae...@daevid.com]
* @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 [dae...@daevid.com]
* @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 [dae...@daevid.com]
 * @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

Reply via email to