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.

  • xsalefter

    Yes. But how about documentation?? If you create some private method and overload using __call magic method, then the other developer never know HOW to use your code. You or me can not create a great framework depend on such language like this..

    This is very annoying thing in PHP.. I don’t know why the core developer doesn’t care about this..

  • You’re right, xsalefter. The problem faced with this technique is the documentation. I never use this kind of technique in my dialy job, because the PHP code becoming unmanagable.

    Obviously, it’s not for production/framework use. So, it’s better to wait PHP 6. I hope there would be feature for methods overloading.

    Talking about encapsulation, the purpose is to hide any methods which defined in __call Magic Method and somehow crashing with our logic. This article’s code is not best practice :). We make fun with it.

    I totally agree with you, that’s one of the reason that PHP would becoming great language start with PHP 6. Which is good news for me, OOP world and 3 tier coding.

    Thanks!

  • seo

    its good but I think its not a suitable solution, is there any other method for achieving overloading in php.

    Thanks.
    http://www.seoinfotech.com