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

У меня есть API для взаимодействия с моим веб-приложением, определенным классом. Перед запуском каждого общедоступного метода необходимо выполнить аутентификацию. Вместо того, чтобы ставить одну и ту же строку снова и снова в каждом методе, я хотел бы использовать функцию magic __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.
  }
}

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

2 ответов


__call фактически работает для всех методов, включая public. Однако причина, по которой он не будет работать, если открытый метод уже существует, заключается в том, что код вне вашего класса уже может получить доступ к открытым членам. __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

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

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