简体   繁体   English

传递函数的最后一个默认参数的值

[英]pass value for last default parameter of function

From very long time i am working on php. 很长一段时间我都在研究php。

But one question may I have no idea about 但是我可能不知道一个问题

like I have one function as bellow: 就像我有一个功能如下:

function hello($param1, $param2="2", $param3="3", $param4="4")

Now whenever I will use this function and if I need 4th params thats the $param4 then still I need to call all as blank like this one: 现在每当我使用这个函数,如果我需要第4个参数那个$ param4那么我仍然需要像这样将所有空白称为空白:

hello(1, '', '', "param4");

So is there any another way to just pass 1st and 4th param in call rather then long list of blanks ? 那么还有另一种方法可以在调用中传递第1和第4个参数而不是长列表空格吗?

Or is there any other standard way for this ? 或者还有其他标准方法吗?

There was an RFC for this named skipparams but it was declined. 有一个这个名为skipparams的RFC,但它被拒绝了。

PHP has no syntactic sugar such as hello(1, , , "param4"); PHP没有语法糖,例如hello(1, , , "param4"); nor hello(1, default, default, "param4"); hello(1, default, default, "param4"); (per the RFC) for skipping optional parameters when calling a function. (根据RFC)在调用函数时跳过可选参数。

If this is your own function then you can choose the common jQuery style of passing options into plug-ins like this: 如果这是你自己的函数,那么你可以选择将选项传递到插件中的常见jQuery样式,如下所示:

function hello( $param1, $more_params = [] )
{
    static $default_params = [
        'param2' => '2',
        'param3' => '3',
        'param4' => '4'
    ];

    $more_params = array_merge( $default_params, $more_params );
}

Now you can: 现在你可以:

hello( 1, [ 'param4'=>'not 4, muahaha!' ] );

If your function requires some advanced stuff such as type hinting then instead of array_merge() you will need to manually loop $more_params and enforce the types. 如果你的函数需要一些高级的东西,比如类型提示然后而不是array_merge()你需要手动循环$more_params并强制执行类型。

One potential way you can do this, while a little bit hacky, may work well in some situations. 一种可能的方法,虽然有点hacky,但在某些情况下可能会运行良好。

Instead of passing multiple variables, pass a single array variable, and inside the function check if the specific keys exist. 传递单个数组变量,而不是传递多个变量,并在函数内部检查特定键是否存在。

function hello($param1, $variables = ["param2" => "2", "param3" => "3", "param4" => "4"]) {
    if(!array_key_exists("param2", $variables)) $variables['param2'] = "2";
    if(!array_key_exists("param3", $variables)) $variables['param3'] = "3";
    if(!array_key_exists("param4", $variables)) $variables['param4'] = "4";

    echo "<pre>".print_r($variables, true)."</pre>";
}

This will allow you to set "param4" in the above variable, while still remaining default on all of the others. 这将允许您在上面的变量中设置“param4”,同时仍然保留所有其他变量的默认值。

Calling the function this way: 以这种方式调用函数:

hello("test", ["param4" => "filling in variable 4"]);

Will result in the output being: 将导致输出:

Array
(
    [param4] => filling in variable 4
    [param2] => 2
    [param3] => 3
)

I don't generally recommend this if it can be avoided, but if you absolutely need this functionality, this may work for you. 如果可以避免,我通常不建议这样做,但如果您绝对需要此功能,这可能对您有用。

The key here is that you have a specifically named index inside the array being passed, that you can check against inside the function itself. 这里的关键是你在传递的数组中有一个特别命名的索引,你可以检查函数本身。

The answer, as I see it, is yes and no. 正如我所看到的,答案是肯定的,不是。

No, because there's no way to do this in a standard fashion. 不,因为没有办法以标准方式做到这一点。

Yes, because you can hack around it. 是的,因为你可以破解它。 This is hacky, but it works ;) 这很hacky,但它有效;)

Example: 例:

function some_call($parm1, $parm2='', $parm3='', $parm4='') { ... }

and the sauce: 和酱:

function some_call_4($parm1, $parm4) {
    return some_call($parm1, '', '', $parm4);
}

So if you make that call ALOT and are tired of typing it out, you can just hack around it. 因此,如果你打电话给ALOT并且厌倦了输入它,你就可以解决它。

Sorry, that's all I've got for you. 对不起,这就是我为你所做的一切。

It is an overhead, but you can use ReflectionFunction to create a class, instance of which that can be invoked with named parameters: 这是一个开销,但您可以使用ReflectionFunction创建一个类,其实例可以使用命名参数调用:

final class FunctionWithNamedParams
{
    private $func;

    public function __construct($func)
    {
        $this->func = $func;
    }

    public function __invoke($params = [])
    {
        return ($this->func)(...$this->resolveParams($params));
    }

    private function resolveParams($params)
    {
        $rf = new ReflectionFunction($this->func);

        return array_reduce(
            $rf->getParameters(),
            function ($carry, $param) use ($params) {
                if (isset($params[$param->getName()])) {
                    $carry[] = $params[$param->getName()];
                } else if ($param->isDefaultValueAvailable()) {
                    $carry[] = $param->getDefaultValue();
                } else {
                    throw new BadFunctionCallException;
                }

                return $carry;
            },  
            []
        );
    }
}

Then you can use it like this: 然后你可以像这样使用它:

function hello($param1, $param2 = "2", $param3 = "3", $param4 = "4")
{
    var_dump($param1, $param2, $param3, $param4);
}

$func = new FunctionWithNamedParams('hello');

$func(['param1' => '1', 'param4' => 'foo']);

Here is the demo . 这是演示

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

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