Nurasto.com Website

My digital scrapbook

Method Overloading in PHP

on under Software and Web Development3 Comments

I wrote PHP post more than ASP.NET does isn’t it? I am increasing it right now.

Okay, I was said that PHP doesn’t support method/function polymorphism or more correct term is overloading, but I was wrong. PHP does support it explicitly which require developer involvement to mimic method overloading like C#, VB.NET or JAVA does.  We could use magic method __call(string $name, array $arguments). I am trying to explain how we could do that in PHP comparing with optional argument like we always do.


So, what is method overloading? the polymorphism allow us to use a same method with variety arguments/parameters regarding the input data type or based on combined argument. As you know you could have two method in same name with different arguments in PHP, like the following example

<?php

class MagicMethod
{
    //query method with one argument
    public function query($query)
    {
        echo '<p>';
        echo 'You are calling query($query, $connection)<br />';
        echo 'Your Query is: '.$query;
        echo '</p>';
    }
    //query method with two arguments
    public function query($query, $connection)
    {
        echo '<p>';
        echo 'You are calling query($query, $connection)<br />';
        echo 'Your Query is: '.$query;
        echo '<br />';
        echo 'Your Connection is: '.$connection;
        echo '</p>';
    }
}

echo '<h1>Method Overloading</h1>';

$magicMethod = new MagicMethod();
$magicMethod->query("SELECT * FROM test");
$magicMethod->query("SELECT * FROM test", "MYSQL OBJECT");

?>

Unfortunately, the result will be like this

Fatal error: Cannot redeclare MagicMethod::query() in D:\xampplite\htdocs\DINTFramework\Polymorphism.php on line 16

This happen because there exist two same method name even they had different arguments. There’s no such distinction in PHP built-in capability.

I know you could use an optional argument in a function in PHP since the arguments has same data-type which is string and you know the sequence of the arguments based on it’s priority when implement the function. The code look like this.

<?php

class MagicMethod
{
    public function query($query, $connection = 'NONE')
    {
        echo '<p>';
        echo 'You are calling query($query, $connection)<br />';
        echo 'Your Query is: '.$query;
        echo '<br />';
        echo 'Your Connection is: '.$connection;
        echo '</p>';

    }
}

echo '<h1>Method Overloading - Optional Arguments Way</h1>';

$magicMethod = new MagicMethod();
$magicMethod->query("SELECT * FROM test");
$magicMethod->query("SELECT * FROM test", "MYSQL OBJECT");
?>

The result will print both of commands.

Since PHP hasn’t strongtype data type, we could ignore arguments data-type right now but you could mimic it by checking argument data-type using is_int(), is_string(), is_bool(), etc and control structure like if, switch inside magic method __call. Okay, this is the code in how to mimic overloading in PHP. I hope PHP 6 engine could handle overload beside namespace.

<?php

/**
 * Using Magic Method to mimic method overloading
 *
 */
class MagicMethod
{
    private function _loadData($sql)
    {
        echo '<p>';
        echo 'You are calling loadData($sql)<br />';
        echo 'Your Query is: '.$sql;
        echo '</p>';
    }

    private function _loadDataWithConn($sql, $connection)
    {
        echo '<p>';
        echo 'You are calling loadData($sql, $connection)<br />';
        echo 'Your Query is: '.$sql;
        echo '<br />';
        echo 'Your Connection is: '.$connection;
        echo '</p>';
    }

    //this is the magic 🙂
    public function __call($method, $args)
    {
        //check whether the method is "query" or not;
        if($method == 'query')
        {
            //we count the arguments array
            $argsLength = count($args);
            switch($argsLength)
            {
                case 1:
                    //call the private method
                    $this->_loadData($args[0]);
                    break;
                case 2:
                    //you could code to check the argument value before proceeding

                    //call the private method
                    $this->_loadDataWithConn($args[0], $args[1]);
                    break;
                default:
                    //ignore;
                    throw new Exception('Arguments not valid');
            }
        }
    }
}

echo '<h1>Methods Overloading</h1>';
$magicMethod = new MagicMethod();
$magicMethod->query("SELECT * FROM testing");
$magicMethod->query("SELECT * FROM testing", "MYSQL OBJECT");
?>

That’s it, nothing more. You could expand the logic based on your need. Have fun.