1

I have several classes with several methods. I would like to execute a function with each method call, without a corresponding call in each method.

Is there a way to automate this? Something like a method listerner?

7
  • 2
    Can you provide some sample code and also explain why you want this behaviour? As far as i know there is no way to achieve this behaviour as you discribed it, but maybe i can come up with a solution when knowing the use case. Commented Jul 11, 2020 at 12:13
  • You can call the function in constructor of each class. Commented Jul 11, 2020 at 12:28
  • I would check the permission for each method. My access control is based on each method. A method is in a profile, a profile is in a group and the group is assigned to a user... Commented Jul 11, 2020 at 12:38
  • 1
    I think what you are describing is some kind of middleware. In Laravel, you don't check the permission for a method, but for a route. And a route is "coupled" to a controller method usually. If you don't want to use Laravel, you could use a router library that supports middleware. Commented Jul 11, 2020 at 13:05
  • @Michael: thanks for the hint, but i'm writing my own framework :-) Commented Jul 11, 2020 at 14:05

1 Answer 1

1

You can declare all your method private and use the magic __call method like this.

<?php

class MyClass
{
    private function doSomething($param1, $param2){ //your previously public method
       echo "do ".$param1." ".$param2;
    }
    private function doSomethingForbidden($param1, $param2){ //your previously public method
       echo "doSomethingForbidden";
    } 

    private function verifyPermission($methodName){
       return in_array($methodName, [
          "doSomething"
       ]);
    }

    public function __call($name, $arguments)
    {
        if($this->verifyPermission($name)){
          return call_user_func_array(array($this, $name), $arguments);
        }else{
          throw new \Exception("You can't do that !");
        }
    }
}

$nc = new MyClass();
$nc->doSomething("pet", "the dog");
//do pet the dog
$nc->doSomethingForbidden("feed", "the birds");
//Fatal error:  Uncaught Exception: You can't do that !

when a method is private or does not exists, PHP will automatically routes the call to a __call method if it exists. From there, you can do what you want (check permission, log things, etc.) and since you are now "inside" your class, you can call your private methods yourself using call_user_func_array with the original arguments.

You can learn more reading the documentation for magic methods https://www.php.net/manual/en/language.oop5.overloading.php#object.call

Sign up to request clarification or add additional context in comments.

2 Comments

I use this a lot for logging purposes. And the other magical method are really useful too (like casting, throwing meaningful exceptions, etc)
@MarcWampfler (and don't forget to mark the answer as good if it resolved your problem !)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.