5

PHP5 中有没有办法只允许某个类或一组类调用特定的函数?例如,假设我有三个类(“Foo”、“Bar”和“Baz”),它们都具有类似名称的方法,并且我希望 Bar 能够调用Foo::foo()但拒绝 Baz 进行调用:

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或类似的修饰符无济于事;但是,这些方法不一定是静态的(为了示例的简单性,我在这里制作它们)。

4

3 回答 3

8

没有语言功能可以给你这种行为,听起来你想模仿像 C++ 朋友类这样的东西?

但是,在 foo() 方法中,您可以使用debug_backtrace找出您的调用者是谁,如果它不想要,则抛出异常!

于 2010-06-03T14:22:45.017 回答
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." );
            }
        }
    }

}
于 2011-09-02T19:22:01.373 回答
2

有点软糖,但是如果您想要一个更简单的内存密集型替代方法来使用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

这不会阻止人们查看代码并解决它,但是在异常中带有合理的消息,您应该能够传达您打算如何使用这些类。

你甚至可以更进一步,使用 php 的魔法和方法实现与 C++ 的友元类非常相似的东西,这意味着你可以在不污染实际方法的情况下进行秘密检查。这样做的缺点是您不会获得 IDE 提示这些方法,因为您需要为它们添加前缀或其他东西,否则会绕过魔术方法。__call()__callStatic()

于 2014-07-31T14:29:56.330 回答