PHP5: ограничить доступ к функции для определенных классов - PullRequest
4 голосов
/ 03 июня 2010

Есть ли в 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 или подобных модификаторов не поможет; однако методы не обязательно являются статическими (я сделал их здесь для простоты примера).

Ответы [ 3 ]

7 голосов
/ 03 июня 2010

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

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

3 голосов
/ 02 сентября 2011

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

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." );
            }
        }
    }

}
2 голосов
/ 31 июля 2014

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

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 ++ , используя магические методы php __call() и __callStatic(), это означало бы, что вы могли бы выполнять секретную проверку, не загрязняя фактические методы. Недостатком этого является то, что вы не получите подсказку IDE для этих методов, потому что вам нужно будет добавить к ним префикс или что-то еще, иначе магические методы будут обойдены.

...