Section 8.14. Magic Methods


8.14. Magic Methods

Whenever you see a method name start with a double underscore, it is a "magic" methodone that PHP has provided that you have not declared yourself. PHP reserves all methods starting with _ _ as magic, which means although you can use them yourself, you may find that a later version of PHP uses them as a magic method and causes conflict.

So far, we've seen the following: _ _sleep( ), _ _wakeup( ), _ _clone( ), _ _construct( ), and _ _destruct( )methods that give you special control over your objects that you would not otherwise be able to have. In order to have a full understanding of OOP in PHP there several more you should know: _ _autoload( ), _ _get( ), _ _set( ), _ _call( ), and _ _toString( ).

8.14.1. _ _autoload( )

This global function is called whenever you try to create an object of a class that hasn't been defined. It takes just one parameter, which is the name of the class you have not defined. If you try to construct an object of a class that PHP does not recognize, PHP will run this function, then try to re-create the object and give you a second chance to load the right class.

As a result, you can write scripts like this:

     function _ _autoload($Class) {             print "Bar class name: $Class!\n";             include "barclass.php";     }     $foo = new Bar;     $foo->wombat( ); 

Here we try and create a new object of type Bar, but it doesn't exist. Therefore, the _ _autoload( ) function is called, with "Bar" being passed in as its first parameter. This then include( )s the file barclass.php, which contains the class definition of Bar. PHP will again try and create a new Bar, and this time it will succeed, which means we can work with $foo as normal.

When creating more advanced scripts, you might try include( )ing the parameter passed into _ _autoload( )that way you just need to define each class in a file of its own, with the file named after the class. This has been optimized so that calls to _ _autoload( ) are cacheddon't be afraid to make good use of this technique. At O'Reilly's Open Source Conference in 2004, one of the lead developers of PHP, Andi Gutmans, said, "After having written many examples and worked with it for some time, I'd only ever code this way"as firm an endorsement as anyone could ask for!

8.14.2. _ _get( )

This is the first of three unusual magic methods, and allows you to specify what to do if an unknown property is read from within your script. For example:

     class Dog {             public $Name;             public $DogTag;             // public $Age;             public function _ _get($var) {                     print "Attempted to retrieve $var and failed...\n";             }     }     $poppy = new Dog;     print $poppy->Age; 

Our Dog class has $Age commented out, and we attempt to print out the Age value of $poppy. When this script is called, $poppy is found to not to have an $Age property, so _ _get( ) is called for the Dog class, which prints out the name of the property that was requestedit gets passed in as the first parameter to _ _get( ). If you try uncommenting the public $Age; line, you will see _ _get( ) is no longer called, as it is only called when the script attempts to read a property that does not exist.

From a practical point of view, this means values can be calculated on the fly without the need to create and use accessor methodsnot quite as elegant, perhaps, but easier to read and write.

8.14.3. _ _set( )

The _ _set( ) magic method complements _ _get( ), in that it is called whenever an undefined property is set in your scripts. Here is one example of how you could use _ _set( ) to create a very simple database table class and perform ad hoc queries as if they were members of the class:

     class MyTable {             public $Name;             public function _ _construct($Name) {                     $this->Name = $Name;             }             public function _ _set($var, $val) {                     mysql_query("UPDATE {$this->Name} SET $var = '$val';");             }             // public $AdminEmail = 'foo@bar.com';     }     $systemvars = new MyTable("systemvars");     $systemvars->AdminEmail = 'telrev@somesite.net'; 

In that script, $AdminEmail is commented out, and therefore does not exist in the MyTable class. As a result, when $AdminEmail is set on the last line, _ _set( ) is called, with the name of the property being set and the value it is being set to passed in as parameters one and two, respectively. This is used to construct an SQL query in conjunction with the table name passed in through the constructor. While this might seem like an odd way to solve the problem of setting key database values, it is pretty hard to deny that the last line of code ($systemvars->AdminEmail...) is actually very easy to read.

This system could be extended to more complicated objects as long as each object knows its own ID number.

PHP lets you set arbitrary values in objects, even if their classes don't have that value defined. If this annoys you (if you used OPTION EXPLICIT in your old Visual Basic scripts, for example) you can simulate the behavior by using _ _get( ) and _ _set( ) to print errors.


8.14.4. _ _call( )

The _ _call( ) magic method is to methods what _ _get( ) is to propertiesif you call meow( ) on an object of class Dog, PHP will fail to find the method and check whether you have defined a _ _call( ) method. If so, your _ _call( ) is used, with the name of the method you tried to call and the parameters you passed being passed in as parameters one and two, respectively.

Here's an example of _ _call( ) in action:

     class Dog {             public $Name;             public function bark( ) {                     print "Woof!\n";             }             // public function meow( ) {                     // print "Dogs don't meow!\n";             // }             public function _ _call($function, $args) {                     $args = implode(', ', $args);                     print "Call to $function( ) with args '$args' failed!\n";             }     }     $poppy = new Dog;     $poppy->meow("foo", "bar", "baz"); 

Again, note that the meow( ) method is commented outif you want to be sure that _ _call( ) is not used if the method already exists, remove the comments from meow( ).

8.14.5. _ _toString( )

The last magic method you need to know about is _ _toString( ), which allows you to set a string value for the object that will be used if the object is ever used as a string. This is a fairly simple magic method, and works like this:

     class Cat {             public function _ _toString( ) {                     return "This is a cat\n";             }     }     $toby = new Cat;     print $toby; 

Making this work in PHP 5 caused quite a lot of headaches for the PHP developersgetting the balance right, as to when objects should be converted and when they should not, took a lot of debating. This feature is quite likely to change in future releases, and if it were not for the fact that it is perfect for use with the SimpleXML extension, I doubt it would have made it into PHP 5 at all. However, for now (2005), this is how it works.



PHP in a Nutshell
Ubuntu Unleashed
ISBN: 596100671
EAN: 2147483647
Year: 2003
Pages: 249

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net