Можно ли ограничить способ вызова метода в PHP? - PullRequest
3 голосов
/ 16 июня 2010

Учитывая, что мой класс выглядит так:

class Methods{
    function a(){
        return 'a';
    }

    function b(){  
        $this->a();   
    }

    function c(){ 
        $this->a();
    }  
}

Можно ли гарантировать, что функция может быть вызвана только из функции b?

В приведенном выше примере функция c должна завершиться ошибкой. Я мог бы просто включить его в функцию b, но в будущем я могу захотеть, чтобы a() вызывался некоторыми новыми функциями (например, d() или e ())

Ответы [ 6 ]

8 голосов
/ 16 июня 2010

Начните с изучения различий между публичным, частным и защищенным методами ... полезно иметь хотя бы базовые знания ООП, прежде чем делать что-то невероятно сложное, как это.Да, возможно использовать debug_backtrace (), чтобы определить, откуда был сделан вызов метода;но это очень большие издержки .... и я не вижу смысла в том, чтобы на самом деле устанавливать такое ограничение.

2 голосов
/ 16 июня 2010

Сначала вы должны взглянуть на модификаторы видимости класса, как предложил Марк Бейкер.Это, вероятно, то, что вы ищете.

Однако, если это не так, следующий код должен работать для вас:

class Methods
{
    private function a()
    {
        $bt = debug_backtrace();
        if(!isset($bt[1]) || $bt[1]['function'] != 'b' || $bt[1]['class'] != get_class($this))
        {
            //Call not allowed
            return NULL;
        }
    }
    function b()
    {
        //allowed
        $this->a();
    }
    function c()
    {
        //not allowed
        $this->a();
    }
}
1 голос
/ 16 июня 2010

Самое близкое к тому, что вы просите - это закрытие (анонимная функция) в метод, которым вы хотите его ограничить. Замыкания недоступны за пределами того метода, в котором они определены. Они обычно используются для определения обратных вызовов и передаются другим методам, но вы можете вызвать их напрямую.

class Methods{
  function b(){
    $a = function() {
      return 'a';
    }; // don't forget the trailing ';'

    $a();   
  }

  function c(){ 
    $this->a(); // fails
  }  
}

Создание метода private или protected предотвратит его вызов из-за пределов класса, но не ограничит, какие методы внутри класса имеют к нему доступ. На каком-то уровне вы должны доверять своему коду, чтобы следовать правилам использования вашего API.

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

Как упоминает @Sjoerd, вы также можете проверить стек вызовов, но согласитесь с @Mark Baker, что в этом нет особой ценности; это похоже на злоупотребление языком и делает ваш код беспорядочным.

0 голосов
/ 21 апреля 2011

На ваш вопрос может распространяться следующее.

class First {
    public function a() {
        $second = new Second();

        // Works in this context!
        $second->b($this);
    }
}

class Second {
    public function b($context) {
        if (!$context instanceof First)
            throw new Exception('Can only be called from context of "First".');
        echo 'b';
    }
}

class Third {
    public function c() {
        $second = new Second();

        // Doesn't work out of context.
        $second->b($this);
    }
}

Предупреждение Это не мешает Third вызывать метод, поскольку он может предоставить ссылку на экземпляр Second. Но это делает процесс более строгим, и ваша документация может указать, почему он работает таким образом.

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

0 голосов
/ 16 июня 2010

Не вижу смысла ограничивать методы внутри того же класса для вызова других методов.

Может быть, ваша модель неверна, и вам нужно создать два класса?Один класс должен быть одна логическая единица (как угодно).

Если вы используете отдельные классы, вы можете использовать private keyword для метода a, и он больше не может быть вызван из-за пределов класса.

0 голосов
/ 16 июня 2010

Не совсем.

  • Вы можете проверить вызывающего, проверив результат debug_backtrace ()
  • Вы можете сделать его приватным, чтобы избежать вызова из-за пределов класса, а затем переместить c () за пределы класса.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...