PHP将function_exists()与参数一起使用

时间:2018-09-11 10:49:27

标签: php

我喜欢尝试PHP。我制作了自己的缩写MVC,并且很开心。所有这些工作(将显示和逻辑分开)使我可以启动主题。使用KISS方法。所以没有MVC / OOP请回答。只是一个个人项目。

在下面的代码中,您可以看到我能够路由我的所有功能。但是我只是注意到一个奇怪的事情,我不确定。我的大部分页面很小,并且由于简单性而很少有参数。所以我制作了一个更大的应用程序(游戏),它当然需要参数,这就是我可以发现错误的地方:-)

使用这种调用函数的方法时,它会完美工作,直到我发送一个参数为止。然后它给了我

  

函数validate()的参数太少,传递了0个

这不是真的。

所以,我理解为什么这行不通,因为$ function是变量而不是实际函数,所以这类似于说$ variable($ argument)是非法的。

只要没有参数,它就可以工作。

看代码,您可以看到我要完成的工作(如果可能的话),该怎么做?如果有的话。 编辑说明

 $view = 'default';
    if (isset($url[0])) $view         = $url[0];`code`
    if (isset($url[1])) $function     = $url[1];
    if (isset($url[2])) $arg         = $url[2];
    if (isset($url[3])) $arg2        = $url[3];    // used for 2 arguments`


if(!empty($function) && function_exists($function)){
        switch(true){
            // add your case logic for your hight arg count down to here
            case(!empty($arg) && !empty($arg2)) : $function($arg,$arg2);  break; // BOTH arg not empty
            case(!empty($arg) && empty($arg2))  : $function($arg);        break; // FIRST arg only
            case(empty($arg) && empty($arg2))   : $function();            break; // BOTH arg EMPTY
            case(empty($arg) &&
                 empty($arg2) &&
                 isset($_POST))                  :$function("hello world");       break; // BOTH arg EMPTY POST set
        }
    }

没有jquery,我更喜欢纯js 同样,这只是一个探索PHP某些功能的个人项目。

你们中的任何一位亲可以帮助我玩这个吗? 谢谢!

特别感谢@Imaginaroom向我指出了正确的方向:

这是更新的代码:

 if(isset($function) && function_exists($function)){
        if(isset($_POST)) {
            call_user_func($function, $_POST);
        }else{
            call_user_func_array($function, array($arg, $arg2));
        }

再次感谢您。在我纠正此问题之后,似乎很多人都有类似的想法。好主意!

它需要一些清理。现在可以正常工作了。而且,更重要的是,它使我能够杀死很多冗余代码。

6 个答案:

答案 0 :(得分:0)

调用变量函数是callables的工作。尽管有PHP / 7的增强功能,它还是一个相当老的功能。您可以使用:

另外(不确定是否需要在这里),您可以使用func_get_args()获取函数接收的所有参数。

答案 1 :(得分:0)

因此,我认为,empty($function)如果尝试调用分配给变量$function的可调用对象,可能会解决该问题,这就是失败的原因(没有对其进行测试)。

但是,function_exists仍然只接受字符串作为参数,该字符串应表示一个函数名称以检查其是否存在(显然)。因此,如果变量$function是函数的名称,则不能像$function($arg, $arg2)那样使用它,而是需要研究call_user_func函数。 另一方面,如果您将函数本身分配给变量$function,则需要将条件从更改为

if(!empty($function) && function_exists($function)) 

if(isset($function) && is_callable($function))

答案 2 :(得分:0)

从错误消息“函数validate()的参数太少,传递了0个值” ,看来$function == 'validate'$arg$arg2为空。请注意,PHP函数empty()还将数字0和字符串"0"视为空值。

您应使用strlen()检查变量是否为空字符串。如果将$arg$arg2设置为从请求中获取的值,则它们是字符串(它们也可以是字符串数组)。

可能的代码重写方式可能是:

if (is_callable($f)) {
    // Collect all the non-empty arguments in $arguments
    $arguments = [];
    // $arg[0] is the first character of the string stored in $arg
    // when it is set (it exists) the string is not empty
    if (isset($arg[0]) {
        $arguments[] = $arg;
    }
    // More arguments
    if (isset($arg2[0]) {
        $arguments[] = $arg2;
    }

    // Call the function with arguments
    call_user_func_array($f, $arguments);
}

详细了解is_callable()isset()call_user_func_array()

答案 3 :(得分:0)

您可以将闭包与参数解压缩一起使用

$closureA = function ($a, $b) { return $a + $b; };
$closureB = function ($a) { return $a * 2; };
$closureC = function () { return 2; };

function run(Closure $closure, array $args = []) {
   return $closure(...$args);
}

echo run($closureA, [1,2]);
echo run($closureB, [2]);
echo run($closureC);

输出:

342

这是运行3个具有不同参数的闭包的结果,即使其中的1个没有args。

Working fiddle

可以将闭包设置为以键作为函数名称的数组,然后使用array_key_exists轻松地检查是否存在这种闭包,然后使用run()函数调用它

以下示例:

$closures = [];
$closures['add'] = function ($a, $b) { return $a + $b; };
$closures['multiplyby2'] = function ($a) { return $a * 2; };
$closures['return2'] = function () { return 2; };

function run(string $name, array $args = []){
   global $closures;
   return array_key_exists($name, $closures) ? $closures[$name](...$args) : "no closure for given name";
}

echo run('add', [1,2]);
echo run('multiplyby2', [2]);
echo run('return2');
echo run('blabla');

Working fiddle

答案 4 :(得分:0)

有很多方法可以实现这一目标

function test($arg1=FALSE,$arg2=FALSE){ // setting default value

    // If you want to check if the values are numeric or something like that
    // $arg1 = $arg1?is_numeric($arg1)?$arg1:FALSE:FALSE;
    // $arg2 = $arg2?is_numeric($arg2)?$arg2:FALSE:FALSE;
    $bothValid = ($arg1 && $arg2)?TRUE:FALSE;

    // Then you can proceed the way you like
    if($bothValid){
        // code that uses both params
        // return something;
    }

    if($arg1){
        // code that uses argument 1
        // return something;
    }

    if($arg2){
        // code that uses argument 2
        // return something;
    }   
}

或类似如下

function test($type,$arg1=FALSE,$arg2=FALSE){ // setting default value

    // If you want to check if the values are numeric or something like that
    // $arg1 = $arg1?is_numeric($arg1)?$arg1:FALSE:FALSE;
    // $arg2 = $arg2?is_numeric($arg2)?$arg2:FALSE:FALSE;

    $bothValid = ($arg1 && $arg2)?TRUE:FALSE;
    switch ($type) {
        case ($type == 'add' && $bothValid):
            return $arg1 + $arg2;
        break;

        default:
            return 'Your error message';
        break;
    }
}

您可以通过以下函数调用进行检查

test();
test(1,2);
test('sdfsdfsf','sdfsdf');

答案 5 :(得分:-2)

将您的函数移至类。然后,您可以简化代码:

class myClass {
    public function foo($arg = null, $arg2 = null) {}

    public function test($function, $arg, $arg2) {
        $args = array_filter([$arg, $arg2]);

        if (method_exists([$this, $function])) {
            if (empty($args) && !empty($_POST)) {
                $function('Hello world');
            } else {
                call_user_func_array([$this, $function], array_filter($args));
            }
        }
    }
}