2010-06-03 5 views
4

Есть ли способ в PHP5 разрешить определенному классу или набору классов вызывать определенную функцию? Например, допустим, у меня есть три класса («Foo», «Bar» и «Baz»), все с похожими методами, и я хочу, чтобы Bar имел возможность вызвать Foo::foo(), но запретить Baz возможность совершить этот вызов :PHP5: ограничить доступ к функции определенным классам

class Foo { 
    static function foo() { print "foo"; } 
} 

class Bar { 
    static function bar() { Foo::foo(); print "bar"; } // Should work 
} 

class Baz { 
    static function baz() { Foo::foo; print "baz"; } // Should fail 
} 

Foo::foo(); // Should also fail

Там не обязательно наследование между Foo, Bar и Baz, поэтому использование protected или подобных модификаторов не поможет; однако методы не обязательно статичны (я сделал их здесь для простоты примера).

ответ

7

Не существует языковой функции, которая могла бы дать вам такое поведение, похоже, что вы хотите эмулировать что-то вроде классов C++ friend?

Однако внутри метода foo() вы можете использовать debug_backtrace, чтобы узнать, кто был вашим абонентом, и выбросить исключение, если оно не хочет вас хотеть!

+0

Не разработчик C++, но после прочтения (кратко) о классах друзей это похоже на то, что я ищу. Удручает, что нет эквивалента PHP. – Tim

3

Я создал функцию для этого, которая может быть полезна.

class HelperClass 
{ 

    static function callOnlyByClass($class_name, $function_name = NULL) 
    { 
     $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); 
     $caller_class = $backtrace[2]["class"]; 
     if($caller_class !== $class_name) { 
      throw new Exception("Only $class_name is allowed to call this function. Was called by $caller_class."); 
     } 
     if(! is_null($function_name)) { 
      $caller_function = $backtrace[2]["function"]; 
      if($caller_function !== $function_name) { 
       throw new Exception("Only $class_name::$function_name is allowed to call this function. Was called by $caller_class::$caller_function."); 
      } 
     } 
    } 

} 
1

Немного выдумки, но если вы хотите более простую меньше памяти интенсивной альтернативы использованию debug_backtrace() вам могут потребоваться дополнительный аргумент метода, который должен был бы быть каким-то конкретного секретного значения. Так, например: -

class Foo { 
    static function foo($arg='') { 
     if ($arg != 'act6hd56') { 
      throw new Exception('Cannot call this method from any class except Bar'); 
     } 
     print "foo"; 
    } 
} 

class Bar { 
    static function bar() { Foo::foo('act6hd56'); print "bar"; } // Works 
} 

Foo::foo(); // Throws exception 

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

Можно даже пойти дальше и реализовать что-то очень похожее на C++ с использованием friend classes магии __call() и __callStatic() методы PHP, это означало бы, вы могли бы сделать секретную проверку, не загрязняя фактические методы. Недостатком этого может быть то, что вы не получите намек IDE для этих методов, потому что вам нужно будет их префикс или что-то в этом роде, иначе магические методы будут обходить.