PHP5: ограничить доступ к функции определенным классам

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

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


person Tim    schedule 03.06.2010    source источник


Ответы (3)


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

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

person Paul Dixon    schedule 03.06.2010
comment
Не разработчик С++, но после прочтения (кратко) о классах друзей это звучит как именно то поведение, которое я ищу. Удручает, что нет эквивалента PHP. - person Tim; 03.06.2010

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

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

}
person Kendall Hopkins    schedule 02.09.2011

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

person rgvcorley    schedule 31.07.2014