0

一些语言允许我们在将参数传递给方法时命名参数,例如:

private static function hello(a, long, list = 0, of = 0, parameters = 0)
{
    ...
}

self::hello(a=1, long=2, list=3, of=4);

在某些情况下,它肯定会简化阅读代码。php中是否有类似的功能?

我能想象的最简单的结构是:

self::hello(/*a*/ 1, /*long*/ 2, /*list*/ 3, /*of*/ 4);

[offtopic]Love Obj C...需要命名参数:[self helloA:1 long:2 list:3 of:4];[/offtopic]

4

2 回答 2

2

PHP不提供这样的功能,但它可以在很大程度上被伪造。我刚写了这个东西。不是 100% 测试,但如果使用正确,它会工作。

如何使用它的示例:

call_user_func_args(function($a1, $a2, array $a3 = null, $a4 = null){
    var_dump(func_get_args());
}, array(
    'a1'    => 1,
    'a3'    => null,
    'a2'    => 2,
));
// Output
array (size=3)
  0 => int 1
  1 => int 2
  2 => null

它在类前面使用,因为它是用于PHP 5.3 或更高版本\的命名空间代码。删除以尝试在 5.2 中使用它,但不能保证。\

这是代码:

/**
* Calls a function with named arguments.
* Just written and quite tested. If you find bugs, please provide feedback and I'll update the code.
* In a sane usage scenario, it will work. If you try your best, you might break it :)
* If true, $ValidateInput tries to warn you of issues with your Arguments, bad types, nulls where they should not be.
* 
* @copyright Claudrian
* @param callable $Callable
* @param array $Arguments
* @param bool $ValidateInput
* @return mixed
*/
function call_user_func_args($Callable, array $Arguments, $ValidateInput = false){
    // Make sure the $Callable is callable
    if(!is_callable($Callable)){
        trigger_error('$Callable is not a callable.', E_USER_WARNING);
        return false;
    }

    // No arguments, no game
    if(empty($Arguments)){
        return call_user_func($Callable);
    }

    // Validate the input $Arguments
    array_change_key_case($Arguments, CASE_LOWER);
    foreach($Arguments as $ArgumentName => $ArgumentValue){
        if(empty($ArgumentName) or is_numeric($ArgumentName)){
            trigger_error('$Arguments cannot have numeric offsets.', E_USER_WARNING);
            return false;
        }
        if(!preg_match('~^[a-z_][a-z0-9_]*$~', $ArgumentName)){
            trigger_error('$Arguments contains illegal character offsets.', E_USER_WARNING);
            return false;
        }
    }

    // Get access to the function
    try {
        $Reflector = new \ReflectionFunction($Callable);
    } catch(\Exception $Exception){
        trigger_error($Exception->getMessage(), E_USER_WARNING);
        return false;
    }

    // If function has not arguments, just call it but it's stupid
    $RequiredParameterCount = $Reflector->getNumberOfRequiredParameters();
    $ParameterCount = $Reflector->getNumberOfParameters();
    if(!$ParameterCount){
        return call_user_func($Callable);
    }

    // Prepare the $Parameters
    $Parameters = array();
    $PresetParameters = array();
    foreach($Reflector->getParameters() as $Parameter){
        $LowerName = strtolower($Name = $Parameter->getName());
        $Argument = ($Available = array_key_exists($Name, $Arguments)) ? $Arguments[$Name] : null;
        $Default = ($IsDefault = $Parameter->isDefaultValueAvailable()) ? $Parameter->getDefaultValue() : null;
        $Parameters[$LowerName] = array(
            'Name'              => $Name,
            'Offset'            => $Parameter->getPosition(),
            'Optional'          => $Parameter->isOptional(),
            'Nullable'          => $Parameter->allowsNull(),
            'Reference'         => $Parameter->isPassedByReference(),
            'Array'             => $Parameter->isArray(),
            'Defaultable'       => $IsDefault,
            'Default'           => $Default,
            'Available'         => $Available,
            'Provided'          => $Available ? $Argument : $Default,
        );
    }

    // Pop pointless nulls (from the last to the first)
    end($Parameters);
    while($Parameter = current($Parameters)){
        if(!$Parameter['Nullable'] or !$Parameter['Optional'] or !is_null($Parameter['Provided'])){
            break;
        }
        array_pop($Parameters); // Pop trailing null optional nullable arguments
        prev($Parameters); // Move one back
    }

    // Prepare the final $Arguments
    $Arguments = array();
    foreach($Parameters as $Name => $Parameter){
        if($ValidateInput){
            if(is_null($Parameter['Provided']) and !$Parameter['Nullable']){
                trigger_error("Argument '{$Name}' does not accept NULL.", E_USER_NOTICE);
            }
            if($Parameter['Array'] and !is_array($Parameter['Provided'])){
                if(!$Parameter['Nullable'] and is_null($Parameter['Provided'])){
                    trigger_error("Argument '{$Name}' should be an array.", E_USER_NOTICE);
                }
            }
            if(!$Parameter['Available'] and !$Parameter['Optional'] and !$Parameter['Defaultable']){
                trigger_error("Argument '{$Name}' is not optional and not provided.", E_USER_NOTICE);
            }
        }
        // Stoe this in the final $Arguments array
        $Arguments[] = $Parameter['Provided'];
    }
    // Invoke the actual function
    return $Reflector->invokeArgs($Arguments);
}
于 2012-11-02T08:53:04.833 回答
0

你可以做

$a=1;
$long=2;
$list=3;
$of=4;
self::hello($a, $long, $list, $of);

其他方式,将是使用 setter 在你打招呼之前设置对象中的值。尽管在您的示例中,它是一种私有方法...

您在这里的参考应该是http://www.php.net/manual/en/functions.arguments.php

于 2012-11-02T08:04:15.533 回答