简体   繁体   English

如何在PHP中检查函数是公共的还是受保护的

[英]How to check if a function is public or protected in PHP

I am building an API where the user requests a 'command', which is passed into a class. 我正在构建一个API,用户请求一个'命令',它被传递给一个类。 Assuming the command matches a PUBLIC function, it will execute successfully. 假设该命令与PUBLIC函数匹配,它将成功执行。 If the command matches a PROTECTED function, it needs to throw an error. 如果命令与PROTECTED函数匹配,则需要抛出错误。

The idea is that functions can be disabled by changing them from PUBLIC to PROTECTED, rather than renaming them or removing them. 这个想法是可以通过将函数从PUBLIC更改为PROTECTED来禁用它们,而不是重命名它们或删除它们。

I currently do this, but it doesn't matter if the command is public or protected. 我目前这样做,但是如果命令是公共的还是受保护的并不重要。

<?php
/**
 * Look for Command method
 */
$sMethod = "{$sCommand}Command";
if (method_exists($this, $sMethod))
{
    /**
     * Run the command
     */
    return $this->$sMethod($aParameters);
}

Simply use ReflectionMethod : 只需使用ReflectionMethod

/**
 * Look for Command method
 */
if (method_exists($this, $sMethod))
{
    $reflection = new ReflectionMethod($this, $sMethod);
    if (!$reflection->isPublic()) {
        throw new RuntimeException("The called method is not public.");
    }
    /**
     * Run the command
     */
    return $this->$sMethod($aParameters);
}

You can use the is_callable function to determine if the protection level should limit you: Example: 您可以使用is_callable函数来确定保护级别是否应该限制您:示例:

<?php
class FooBar {
    protected function Foo() { return; }
    public function Bar() { return; }
}

$foo = new FooBar();

var_dump(is_callable(array($foo, 'Foo')));
var_dump(is_callable(array($foo, 'Bar')));

Though you can not differentiate if the method is private or protected, you can test if public versus not using an external method using is_callable . 虽然您无法区分方法是隐私还是受保护,但您可以使用is_callable测试公共与否使用外部方法。 I made a comparison with "meze" answer. 我与“meze”答案进行了比较。

So: 所以:

function testIfCallable($object, $method) {
    return is_callable(array($object, $method));
}

function testIfCallable2($object, $method) {
    if (method_exists($object, $method))
    {
        $reflection = new ReflectionMethod($object, $method);
        return $reflection->isPublic();
    }

    return false;
}

class Test {

    private function privateMethod() {

    }

    protected function protectedMethod() {

    }

    public function publicMethod() {

    }

    public function testAccessibility() {
        if (testIfCallable($this, 'privateMethod')) echo "YYY<br>"; else echo 'NNN<br>';
        if (testIfCallable($this, 'protectedMethod')) echo "YYY<br>"; else echo 'NNN<br>';
        if (testIfCallable($this, 'publicMethod')) echo "YYY<br>"; else echo 'NNN<br>';
    }

    public function testAccessibility2() {
        if (testIfCallable2($this, 'privateMethod')) echo "YYY<br>"; else echo 'NNN<br>';
        if (testIfCallable2($this, 'protectedMethod')) echo "YYY<br>"; else echo 'NNN<br>';
        if (testIfCallable2($this, 'publicMethod')) echo "YYY<br>"; else echo 'NNN<br>';
    }       

    public function testSpeedAccessibility() {
        return $results = [
                testIfCallable($this, 'privateMethod'),
                testIfCallable($this, 'protectedMethod'),
                testIfCallable($this, 'publicMethod')
        ];
    }

    public function testSpeedAccesibility2() {
        return $results = [
                testIfCallable2($this, 'privateMethod'),
                testIfCallable2($this, 'protectedMethod'),
                testIfCallable2($this, 'publicMethod')
        ];
    }
}

The method testIfCallable shall be included in a Common class or something similar which you have in your own toolkit because global methods aren't recommended. 方法testIfCallable应包含在您自己的工具包中的Common类或类似的东西中,因为不建议使用全局方法。

I use this in conjunction with the magic methods __get and __set to ensure a public "get/set" method exists. 我将它与魔术方法__get__set结合使用,以确保存在公共的“get / set”方法。

Tests : 测试:

//Test functionality
$t = new Test();
$t->testAccessibility();
$t->testAccessibility2();

//Test speed
$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
    $t->testSpeedAccessibility();
}
echo "Is Callable way: " . (microtime(true) - $start) . "ms<br>";

$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
    $t->testSpeedAccesibility2();
}
echo "Reflection way: " . (microtime(true) - $start) . "ms<br>";

Outputs: 输出:

NNN
NNN
YYY
NNN
NNN
YYY
Is Callable way: 0.23506498336792ms
Reflection way: 0.45829010009766ms

Final thoughts 最后的想法

If you need to test between all the visibility possibilities, your only way to go is to use testIfCallable2 , so the "meze"'s answer. 如果你需要在所有可见性之间进行测试,你唯一的方法就是使用testIfCallable2 ,所以“meze”的回答。 Otherwise, my way is about twice faster. 否则,我的方式快两倍。 As your question was only between public or not, you could benefit using this. 由于您的问题仅在公众与否之间,您可以从中受益。 Saying that, if you don't use it often, the difference is not significant. 说,如果你不经常使用它,差异并不显着。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM