Posted on Wednesday, 13th August 2008 by Lee

Overloading PHP So That empty() Works

PHP5 has a much improved object oriented feature set. With great MVC PHP frameworks such as CodeIgniter, CakePHP, and the Zend Framework you should certainly be writing your own classes and taking advantage of objects in your coding. Using the magic methods that you get with PHP5 you can overload your classes so that you can do some very cool stuff.

PHP’s overloading deviates from the way other programming languages work. Overloading in most other languages enables you to define several different methods all with the same name but taking different types of paramters. PHP, on the other hand, uses overloading to handle calls to object members or methods that have not been defined or are not visible in the current scope of the caller.

A Quick Example Of Overloading

Suppose you define a private assoc array to store the data used by your class. Instead of defining bunches of accessor functions, you can take advantage of the __get() and __set() magic methods.

PHP:
  1. <?php
  2. class Person {
  3.   private $_data = array();
  4.  
  5.   public function __set($key, $value) {
  6.     $this->_data[$key] = $value;
  7.   }
  8.  
  9.   public function __get($key) {
  10.     $value = false;
  11.     if(array_key_exists($key, $this->_data)) {
  12.       $value = $this->_data[$key];
  13.     }
  14.     return $value;
  15.   }
  16. }
  17. ?>

With this class you can use code like this to set and retrieve values from the private $_data array.

PHP:
  1. <?php
  2. class Person {
  3.   private $_data = array();
  4.  
  5.   public function __set($key, $value) {
  6.     $this->_data[$key] = $value;
  7.   }
  8.  
  9.   public function __get($key) {
  10.     $value = false;
  11.     if(array_key_exists($key, $this->_data)) {
  12.       $value = $this->_data[$key];
  13.     }
  14.     return $value;
  15.   }
  16. }
  17. ?>

The Gotcha!

Suppose you want to know if your new Person object has a value for name. You might write code like this.

PHP:
  1. $worker = new Person();
  2. $worker->name = "Lee";
  3. if(empty($worker->name)) {
  4.   echo "This worker has no name!";
  5. }
  6. else {
  7.   echo $worker->name;
  8. }
  9.  
  10. /**
  11. * OUTPUT:
  12. * This worker has no name.
  13. */

So what’s up with that? We just defined the worker’s name? The deal is you have to implement the magic __isset() method. The __isset() method is triggered whenever you call non-magic isset() method or the empty() method. So to get everything working as you would expect it to, be sure to define your own magic __isset() method like this.

PHP:
  1. public function __isset($key) {
  2.   return isset($this->_data[$key]);
  3. }

The complete class definition will look like this.

PHP:
  1. <?php
  2. class Person {
  3.   private $_data = array();
  4.  
  5.   public function __set($key, $value) {
  6.     $this->_data[$key] = $value;
  7.   }
  8.  
  9.   public function __get($key) {
  10.     $value = false;
  11.     if(array_key_exists($key, $this->_data)) {
  12.       $value = $this->_data[$key];
  13.     }
  14.     return $value;
  15.   }
  16.  
  17.   public function __isset($key) {
  18.     return isset($this->_data[$key]);
  19.   }
  20. }
  21. ?>

Now when you run this code, you get the answer you would expect.

PHP:
  1. $worker = new Person();
  2. $worker->name = "Lee";
  3. if(empty($worker->name)) {
  4.   echo "This worker has no name!";
  5. }
  6. else {
  7.   echo $worker->name;
  8. }
  9.  
  10. /**
  11. * OUTPUT:
  12. * Lee
  13. */

Now you know... and knowing is half the battle.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists

Posted in PHP, Web Development | Comments (1)

One Response to “Overloading So That empty() works in PHP”

  1. Artem Says:

    I found that using magic methods also helps with creating a quasi-factory method for your classes.

    Here is a simplified example of a database class that uses drivers.

    Class: Database

    Class: Database_Driver

    Class: Database_Driver_MySQL

Leave a Reply