• Aucun résultat trouvé

__isset and __unset

Dans le document PHP OBJECT-ORIENTED (Page 133-136)

PHP 5.1.0 introduces the magic methods __isset and __unset. These methods are called indirectly by the built-in PHP functions isset and unset. The need for these magic methods results directly from the existence of magic set and get methods for undeclared data members. The magic method __isset will be called whenever isset is used with an undeclared data member.

Suppose you want to determine whether the name variable of your Person instance in Listing 13-1 has been set. If you execute the code isset($t->name);, the return value will be false. To properly check whether an undeclared data member has been set, you need to define an __isset method. Redo the code for the Person class to incorporate a magic __isset method (see Listing 13-2).

class Person{

protected $datamembers = array();

private $declaredvar = 1;

public function __set($variable, $value){

//perhaps check value passed in $this->datamembers[$variable] = $value;

}

public function __get($variable){

return $this->datamembers[$variable];

}

function __isset($name){

return isset($this->datamembers[$name]);

}

function getDeclaredVariable(){

return $this->declaredvar;

} }

$p = new Person();

$p->name = 'Fred';

echo '$name: '. isset($p-> name). '<br />';//returns true

$temp = $p->getDeclaredVariable();

echo '$declaredvar: '. isset( $temp). '<br />';//returns true true

true

Listing 13-2: The Person class with a magic __isset method

Calling isset against the undeclared data member name will return true because an implicit call is made to the __isset method. Testing whether

a declared data member is set will also return true, but no call, implicit or otherwise, is made to __isset. We haven’t provided an __unset method, but by looking at the __isset method you can easily see how an undeclared variable might be unset.

You have __isset and __unset methods only because there are magic set and get methods. All in all, in most situations, it seems simpler to forget about using undeclared data members, and thereby do away with the need for magic set and get methods and their companion __isset and __unset methods.

__call

The magic method __call is to undeclared methods what __get and __set are to undeclared data members. This is another magic method provided as a con-venience. At first, it is a little difficult to imagine what an undeclared method might be and what use it might have. Well, here’s one way that this method

More Mag ic Met h ods 115 can prove useful. Suppose you wanted to add to the functionality of the MySQLResultSet class defined in Chapters 9 and 10, so as to retrieve the current system status in this fashion:

//assume $rs is an instance of MySQLResultSet

$rs->stat();

You could just create a wrapper method for the existing MySQL function, mysql_stat, as you did when creating other methods of this class. For example, the existing getInsertId method simply encloses a call to mysql_insert_id. You could do exactly the same thing with mysql_stat. However, the more versatile option is to add a __call method similar to the following code:

public function __call($name, $args){

$name = "mysql_". $name(;

if(function_exists($name)){

return call_user_func_array($name, $args);

} }

When you call the stat method against a MySQLResultSet object, the method name, stat, is passed to the __call method where mysql_ is prepended. The mysql_stat method is then invoked by the call_user_func_array function. Not only can you call the mysql_stat function, but once __call is defined you can call any MySQL function against a MySQLResultSet class instance by simply using the function name, minus the leading mysql_, and supplying any required arguments. This magic method does away with the need for writing wrapper methods for existing MySQL function, and allows them to be “inherited.” If you’re already familiar with the MySQL function names it also makes for easy use of the class.

However, this magic method is not quite as convenient as it might seem at first glance. Functions such as mysql_fetch_array that require that a result set resource be passed even though the class is itself a result set resource make nonsense of the whole notion of an object—why should an object need to pass a copy of itself in order to make a method call? On the other hand, this is an easy and natural way to incorporate functions such as mysql_stat and mysql_errno that don’t require any arguments, or functions such as mysql_escape_string that require primitive data types as arguments. If properly used, this convenience method seems much more defensible than the __set and __get methods.

__autoload

The __autoload function is a convenience that allows you to use classes without having to explicitly write code to include them. It’s a bit different from other magic methods because it is not incorporated into a class definition. It is simply included in your code like any other procedural function.

Normally, to use classes you would include them in the following way:

require 'MySQLResultSet.php';

require 'MySQLConnect.php';

require 'PageNavigator.php';

require 'DirectoryItems.php';

require 'Documenter.php';

These five lines of code can be replaced with the following:

function __autoload($class) { require $class '.php';

}

The __autoload function will be invoked whenever there is an attempt to use a class that has not been explicitly included. The class name will be passed to this magic function, and the class can then be included by creating the filename that holds the class definition. Of course, to use __autoload as coded above, the class definition file will have to be in the current directory or in the include path.

Using __autoload is especially convenient when your code includes numer-ous class files. There is no performance penalty to pay—in fact, there may be performance improvements if not all classes are used all the time. Use of the __autoload function also has the beneficial side effect of requiring strict naming conventions for files that hold class definitions. You can see from the previous code listing that the naming conventions used in this book (i.e., combining the class name and the extension .php to form the filename) will work fine with __autoload.

Dans le document PHP OBJECT-ORIENTED (Page 133-136)