PHP5: restrict access to function to certain classes
Is there a way in 开发者_StackOverflow社区PHP5 to only allow a certain class or set of classes to call a particular function? For example, let's say I have three classes ("Foo", "Bar", and "Baz"), all with similarly-named methods, and I want Bar to be able to call Foo::foo()
but deny Baz the ability to make that call:
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
There's not necessarily inheritance between Foo, Bar, and Baz, so the use of protected
or similar modifiers won't help; however, the methods aren't necessarily static (I made them so here for the simplicity of the example).
There's no language feature which could give you that behaviour, sounds like you want to emulate something like C++ friend classes?
However, inside the foo() method you could use debug_backtrace to find out who your caller was, and throw an exception if its not want you want!
I've create a function for doing this that might be helpful.
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." );
}
}
}
}
A bit of a fudge, but if you wanted a simpler less memory intensive alternative to using debug_backtrace()
you could require an additional argument to the method that would have to be of some specific secret value. So for example:-
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
This doesn't stop someone looking through the code and working around it, however with a sensible message in the exception you should be able to convey how you intended the classes to be used.
You could even go further and implement something very similar to C++'s friend classes using php's magic __call()
and __callStatic()
methods, this would mean you could do the secret checking without polluting the actual methods. The disadvantage of this would be you wouldn't get the IDE hinting for those methods because you would need to prefix them or something, otherwise the magic methods are bypassed.
精彩评论