4

I want a function that will be called every time a class is referenced (called). The magic function autoload does a similar thing, but works only if the referenced class doesn't exist. I want to make a function that will work in any case.

For example:

<?php

class Foo {

    static function bar () {
        ...
    }
}

function __someMagicFunction ($name) {
    echo 'You called class ' . $name;
}

Foo::bar(); // Output: You called class Foo

I want the output to be "You called class Foo".

How can i do it? Thanks :)

areller
  • 4,800
  • 9
  • 29
  • 57

2 Answers2

3

Well, there's no easy way to do this, but it is possible. Still, the way you'll have to go about achieving this is not to be recommended, as it will result in slow code. However, here's a simple way to do this:

class Foo
{
    //protected, not public
    protected static function bar ()
    {
    }
    protected function nonStaticBar()
    {
    }
    public function __call($method, array $args)
    {
        //echoes you called Foo::nonStaticBar
        printf('You called %s::%s', get_class($this), $method);
        //perform the actual call
        return call_user_func_array([$this, $method], $args);
    }
    //same, but for static methods
    public static function __callStatic($method, array $args)
    {
        $calledClass = get_called_class();//for late static binding
        printf('You called %s::%s statically', $calledClass, $method);
        return call_user_func_array($calledClass . '::' . $method, $args);
    }
}
$foo = new Foo;
$foo->nonStaticBar();//output: You called Foo::nonStaticBar
Foo::bar();//output: You called Foo::bar statically

The reason for __callStatic using get_called_class rather than get_class(self); is that it enables you to declare the magic methods as final, and still have them work as expected in child classes:

class Foobar extends Foo
{}

Foobar::bar();//output: You called Foobar::bar statically

demo

more details on magic methods:

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • Thank you. I've considered this approach, but i want a function that will do for job for any class, not only those who extend the Foo class. Needless to say that i don't want the implementation of such function to be inside the class itself. – areller Jun 30 '15 at 11:33
  • @Arik: Like I said, there's no easy way to do this, other than have _all_ classes extend from the base class, and not have any public methods at all. Might I ask _why_ you want to do this, because I suspect there's an X-Y problem at play here – Elias Van Ootegem Jun 30 '15 at 11:37
-1

use

 public function __construct(){
}
Bhavin Shah
  • 92
  • 10