__call эквивалент для общедоступных методов

У меня есть API для взаимодействия с моим веб-приложением, определенным классом. Каждому общедоступному методу необходимо выполнить аутентификацию перед запуском. Вместо того, чтобы повторять одну и ту же строку в каждом методе, я хотел бы использовать магическую функцию __call. Тем не менее, он будет работать только на частных или защищенных методах, а мой должен быть общедоступным для работы с Zend_Json_Server.

class MY_Api
{
  public function __call($name, $arguments)
  {
    //code here that checks arguments for valid auth token and returns an error if false
  }

  public function myFunction($param1, $param2, $param3)
  {
    //do stuff when the user calls the myFunction and passes the parameters
    //this function must remain public so that Zend_Json_Server can parse it
    //but I want it intercepted by a magic method so that the authentication
    //can be checked and the system bails before it even gets to this function.
  }
}

Можно ли подключиться к этим публичным функциям и, возможно, отменить их выполнение до их вызова?

Ответ 1

__call действительно работает для всех методов, включая общедоступные. Однако причина, по которой он не будет работать, если общедоступный метод уже существует, заключается в том, что код вне вашего класса уже может обращаться к публичным пользователям. __call вызывается только для членов, которые недоступны вызывающему коду.

Насколько я знаю, на самом деле нет вариантов делать то, что вы ищете, за исключением использования какого-то шаблона декоратора:

class AuthDecorator {
    private $object;

    public function __construct($object) {
        $this->object = $object;
    }

    public function __call($method, $params) {
        //Put code for access checking here

        if($accessOk) {
            return call_user_func_array(array($this->object, $method), $params);
        }
    }
}

$api = new MY_Api();
$decoratedApi = new AuthDecorator($api);

//any calls to decoratedApi would get an auth check, and if ok, 
//go to the normal api class' function

Ответ 2

Поскольку вы пошли с моим комментарием как возможное решение, я отформатировал его в ответ для потомков:

Если решения, ориентированные на аспекты или декорации, не сработают для вас, вы можете попробовать более основанное на каркасе решение, поместив код, который проверяет подлинность либо в вызывающем абоненте вашего общедоступного метода, либо даже выше.