Wednesday, 17 September 2014

PHP equivalence: onMissingMethod()

G'day:
Whilst looking at overloading in PHP before ("Looking at PHP's OOP from a CFMLer's perspective: overloading (which is not what you'd assume it is)"), I thought I might need to write an equivalent on onMissingMethod(), to catch instances of me calling... methods which I expected not to exist. I didn't need to because PHP works differently form how I expected it to, but it piqued my interest so I've just looked up how this is done. It's easy.



Here's a CFML example:

// Missing.cfc
component {
    public function onMissingMethod(name, args) {
        writeDump(arguments);
    }
}

// missing.cfm
missing = new Missing();

missing.nonExistent("first",["second"]);

Nothing out of the ordinary there. It outputs:

Scope Arguments
name1
stringnonExistent
args2
Scope Arguments
11
stringfirst
22
Array
1
stringsecond

So the first argument is the function that was called (and does not exist), and the second are the arguments passed to it.

Very similarly, here's the PHP equivalent:

<?php
// Missing.class.php

class Missing
{

    public function __call($name, $arguments)
    {
        require "../../../debug/dBug.php";
        new dBug(func_get_args());
    }
}

<?php
// missing.php

require "Missing.class.php";

$missing = new Missing();

$missing->nonExistent("first", ["second"]);

And the output here is:

func_get_args() (array)
0nonExistent
1
array
0first
1
array
0second

So __call() is the PHP equivalent of onMissingMethod(), and works pretty much the same way.

PHP also has the notion of static methods, and there's a handler for missing static methods too. Here's a variation of the above code... the difference is basically we use __callStatic() instead:
<?php
// Missing.class.php

require "../../../debug/dBug.php";

class Missing
{

    public function __call($name, $arguments)
    {
        echo sprintf("Function called: %s", __FUNCTION__);
        new dBug(func_get_args());
    }

    public static function __callStatic($name, $arguments)
    {
        echo sprintf("Function called: %s", __FUNCTION__);
        new dBug(func_get_args());
    }
}


<?php
// missing.php

require "Missing.class.php";

$missing = new Missing();

$missing->nonExistent("first", ["second"]);
echo "<hr>";

Missing::nonExistent("tuatahi", ["tuarua"]);

This outputs:

Function called: __call
func_get_args() (array)
0nonExistent
1
array
0first
1
array
0second

Function called: __callStatic
func_get_args() (array)
0nonExistent
1
array
0tuatahi
1
array
0tuarua

So that's straight forward too.

I realise there's not much insight to this article, but I just wanted to share when things go smoothly as well as when I get undone by weirdness / ignorance.

--
Adam