Using Method Call Overloading in PHP 4

This is part two of the series “Overloading classes in PHP.” In three tutorials, this series teaches how to overload your classes in PHP 4 by using the “overload()” PHP built-in function, in conjunction with the implementation of the “__set()”, “__get()” and “__call()” methods, and explores the native support of object overloading in PHP 5.

Introduction

As usual, I’d like to refresh the topics that I covered in the first part of this series, regarding the overloading of classes in PHP 4, so it will be much easier to come back to the subject and continue exploring its most relevant aspects. Stepping back to the previous tutorial, you’ll certainly remember that I went through the key points of overloading classes in PHP, and paid close attention to explaining the implementation of the “__set()” and “__get()” methods, which can be called automatically, after a given class has been overloaded.

Particularly, I showed you how to trigger the methods by overloading several property accesses. This can be quite useful, particularly if you want to run custom code without the need to explicitly call these methods. As you learned before, after a class has been overloaded by the “overload()” function, the PHP 4 interpreter will enable this functionality, which can be used in different clever ways.

All right, after refreshing the concepts that I covered in the previous tutorial, it’s time to focus on the current one. In this second article, I’ll first show you how to combine the two “__set()” and “__get()” methods into one single class, so they can be properly triggered when overloading a property access. Then I’ll teach you how to overload a method call, in order to trigger the homonymous “__call()” method.

After defining the topics to be covered in this second article, let’s move on and continue exploring the different approaches for overloading classes in PHP 4. It’s going to be really instructive!

{mospagebreak title=Going backwards: a quick look at a previous example}

Before I explain how to combine the two “__set()” and “__get()” methods within the same overloaded class, you should take a brief look at the sample “CookieSaver” class that I wrote in the first article, which provides a concrete implementation of the “__set()” method. Here is the signature of this class, according to its original definition:

class CookieSaver{
    var $cookieName;
    var $value;
    var $expTimes=array(‘exp1’=>900,’exp2’=>1800,’exp3’=>3600);
    function CookieSaver
($cookieName=’defaultCookie’,$value=’defaultValue’){
        if(!is_string($cookieName)){
            trigger_error(‘Invalid cookie name’,E_USER_ERROR);
        }
            $this->cookieName=$cookieName;
            $this->value=$value;
    }
    // set cookie
    function setCookie(){
        setcookie($this->cookieName,$this->value);
    }
    // get cookie
    function getCookie(){
        if(!$cookie=$_COOKIE[$this->cookieName]){
            trigger_error(‘Error retrieving
cookie’,E_USER_ERROR);
        }
        return $cookie;
    }
    // set value of property via __set() method
    function __set($property,$value){
        $this->expTimes[$property]=$value;
        $expTime=$this->expTimes[$property];
        setcookie(‘newCookie’,urlencode(‘This cookie has been set
via the __set() method’),time()+$expTime);
        echo ‘Setting new cookie…with an expiration of ‘.$expTime.’ seconds.';
        return;
    }
}

Assuming that the above class is now fresh in your mind, below I listed a simple script that triggers the “_set()” method when a property access is overloaded. Take a look please:

// instantiate ‘CookieSaver’ object
$cookieSaver=&new CookieSaver();
// set cookie
$cookieSaver->setCookie();
// call __set() method and modify $this->expTimes['exp1'] array
element
@$cookieSaver->exp1=3600;

In this case, the previous code sample demonstrates a crude implementation of how to overload a property access, in order to automatically run the code defined inside the __”set()” method. After running the previous script, its output is the following:

Setting new cookie…with an expiration of 3600 seconds.

Now that you remember how to call a “__set()” method, and also a “__get()” method via the corresponding overloading of a property access, let’s see how both methods can be combined inside the same “CookieSaver” class. To learn how this will be done, please read the following section of the article.

{mospagebreak title=Overloading multiple property accesses: combining the “__set()” and “__get()” methods in a single class}

Combining the “__set()” and “__get()” methods into one single class is really a no-brainer process. Once the structure of the class has been defined, it’s just a matter of adding a concrete implementation for each of the methods. Using the previous “CookieSaver” class, here is how the two respective methods can be combined:

class CookieSaver{
    var $cookieName;
    var $value;
    var $expTimes=array(‘exp1’=>900,’exp2’=>1800,’exp3’=>3600);
    function CookieSaver($cookieName=’defaultCookie’,$value=’defaultValue’){
        if(!is_string($cookieName)){
            trigger_error(‘Invalid cookie name’,E_USER_ERROR);
        }
            $this->cookieName=$cookieName;
            $this->value=$value;
    }
    // set cookie
    function setCookie(){
        setcookie($this->cookieName,$this->value);
    }
    // get cookie
    function getCookie(){
        if(!$cookie=$_COOKIE[$this->cookieName]){
            trigger_error(‘Error retrieving
cookie’,E_USER_ERROR);
        }
        return $cookie;
    }
    // set value of property via __set() method
    function __set($property,$value){
        $this->expTimes[$property]=$value;
        $expTime=$this->expTimes[$property];
        setcookie(‘newCookie’,urlencode(‘This cookie has been set
via the __set() method’),time()+$expTime);
        echo ‘Setting new cookie…with expiration of ‘.$expTime.’ seconds.';
        return;
    }
    // get value of property via __get() method
    function __get($property){
        $expTime=$this->expTimes[$property];
        setcookie(‘newCookie’,urlencode(‘This cookie has been set
via the __get() method’),time()+$expTime);
        echo ‘Retrieving new cookie…with an expiration of
‘.$expTime.’ seconds.';
        return;
    }
}

As you can see, the above class now includes both the “__set()” and “__get()” methods that you saw previously. This comes in very handy for demonstrating how they can be triggered together when the class is properly overloaded by the “overload()” function.

With reference to this, the following code snippet shows how to overload the class, and how the corresponding “__get()” and “__set()” method are automatically called behind the scenes when the same property access is overloaded in turn:

// overload ‘CookieSaver’ class ( implements __set() and __get()
methods)
overload(‘CookieSaver’);
// instantiate ‘CookieSaver’ object
$cookieSaver=&new CookieSaver();
// call __set() method and modify $this->expTimes['exp1'] array
element
@$cookieSaver->exp1=60;
// call __get() method and return $this->expTimes['exp1'] array
element
echo @$cookieSaver->exp1;

In the previous example, when the first property access is overloaded, it gives as output the following message:

Setting new cookie…with an expiration of 60 seconds.

Obviously, this means that the “__set()” method has been triggered by the PHP parser and a new cookie has been set. In a similar fashion, when the second property access is overloaded, the script displays the following message:

Retrieving new cookie…with an expiration of 900 seconds.

This time, after overloading the second property access, the “_get()” method has been called, and as a result, the cookie has been retrieved by this method. Also, it should be noted that both property accesses must not be overloaded at the same time. An error will be triggered if you do this, because the two “__set()” and “__get()” methods first set a cookie and then display a simple message. As you know, you cannot output anything before handling cookies (at least not directly) when using the HTTP protocol.

Right, at this point you’ve seen how the two “__set()” and “__get()” methods were combined within the same sample class, to be triggered by the PHP interpreter when a couple of property accesses are overloaded. Assuming that you already grasped the core concepts of how to overload a property access, the last example that I’m going to show you in this article is aimed at demonstrating how to overload a method call. It will result in the triggering of the respective “__call()” method.

To learn how this will be achieved, please jump into the next section and keep on reading.

{mospagebreak title=Triggering the “__call()” method in the background: overloading a method call}

As I mentioned before, the last example that I’ll show you illustrates how a “__call()” method can be triggered when a method call is overloaded. To clarify this concept, let me tell you that if a specific class has been overloaded by the “overload()” function, then it’s possible to trigger a “__call()” method automatically by using a method call, if the class provides a concrete implementation of it.

Does this sound confusing? Well, in order to simplify things, first I’ll redefine the previous “CookieSaver” class, so it will provide a concrete definition of a “__call()” method. This is how the class now looks:

// define ‘CookieSaver’ class and implement __call() method
class CookieSaver{
    var $cookieName;
    var $value;
    var $expTimes=array(‘exp1’=>900,’exp2’=>1800,’exp3’=>3600);
    function CookieSaver
($cookieName=’defaultCookie’,$value=’defaultValue’){
        if(!is_string($cookieName)){
            trigger_error(‘Invalid cookie name’,E_USER_ERROR);
        }
        $this->cookieName=$cookieName;
        $this->value=$value;
    }
    // set cookie
    function setCookie(){
        setcookie($this->cookieName,$this->value);
    }
    // get cookie
    function getCookie(){
        if(!$cookie=$_COOKIE[$this->cookieName]){
            trigger_error(‘Error retrieving
cookie’,E_USER_ERROR);
        }
        return $cookie;
    }
    // set cookie via __call () method
    function __call($method,$arguments){
        $expTime=$this->expTimes[$arguments[0]];
        setcookie(‘newCookie’,urlencode(‘This cookie has been set
via the __call() method’),time()+$expTime);
        echo ‘Calling ‘.$method.'() method, which sets a new
cookie with an expiration of ‘.$expTime.’ seconds.';
        return;
    }
}

As shown above, the “CookieSaver” class looks nearly identical to the previous examples, except that now the class provides a concrete implementation of the “__call()” method. As you can see, the generic structure of this method is the following:

function __call($method,$arguments){
    // method definition goes here
}

The skeleton of this method should give you a clearer idea, with reference to its input parameters. Yep, you guessed right; when this method is called, it will take up the name of the initial method that was invoked along with an array containing its arguments. Here’s an example that shows the complete process for overloading a method call, which results in the triggering of the previous “_call()” method. Please study the code listed below:

// overload ‘CookieSaver’ class and implement the __call() method
overload(‘CookieSaver’);
// instantiate ‘CookieSaver’ object
$cookieSaver=&new CookieSaver();
// set cookie via __call() method
@$cookieSaver->setExpTime(‘exp1′,’exp2′,’exp3′);

Things are getting exciting now! If you analyze the above script, you’ll notice the following line:

@$cookieSaver->setExpTime(‘exp1′,’exp2′,’exp3′);

What I’m doing here basically is overloading a method call, in this case “setExpTime()”, in order to trigger the corresponding “__call()” method. As you noticed, I’m using a nonexistent method to do this, so I coded the “@” error suppressor before the expression.

Of course, I have to admit the code isn’t elegant at all, but it does trigger the “__call()” method, as shown below:

Calling setexptime() method, which sets a new cookie with an
expiration of 900 seconds.

As you saw, the example above shows a crude implementation of overloading a method call, which results in the pertinent “__call()” method being triggered by the PHP parser. Again, I’d like to emphasize that the example focuses on demonstrating the functionality of method call overloading, to the detriment of the code’s elegance.

Wrapping up

Over this second part of the series I showed you how to combine the “__set()” and “__get()” methods inside the same class, in order to trigger them when a pair of property accesses are overloaded. Also, you learned how to overload a method call, which triggers the corresponding “__call()” method. Since class overloading isn’t natively supported in PHP 4, I used some code workarounds to keep things working properly.

In the last tutorial, I’ll teach you how to implement object overloading in PHP 5. See you in the next part!

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort