PHP 键 => 值数组到方法参数(顺序?)

PHP key => value array to method arguments (order?)

我觉得这个挺有意思的!!! :).


我得到了什么?

在我在某些对象的某种程度上使用的应用程序中(并不重要)我得到一个数组,例如:

$array = array(
    'argument_label' => 'value_label',
    'argument_name' => 'value_name',
    'argument_id' => 'value_id'
)

我对这个数组的创建方式和时间没有任何影响。接下来,我有一个方法:

public function arrayArgument($array) {
    $label = isset($array['argument_label']) ? $array['argument_label'] : 'default_label';
    $name = isset($array['argument_name']) ? $array['argument_name'] : 'default_name';
    $id = isset($array['argument_id']) ? $array['argument_id'] : 'default_id';

    // Do something
    return 'something';
}

我真的很讨厌它。没有办法为方法参数提供适当的文档(因为 PHPDocumentator 不能很好地处理数组),这些 issets 快把我逼疯了。此外,对于将来使用此代码的人来说,这将是一场噩梦,那时我已经是一个“退休的书呆子”了。


我想要什么?

我想要这样的功能:

public function notArrayArgument(
    $id='default_id', 
    $label='default_label', 
    $name='default_name'
) {
    // Do something
    return 'something';
}

我能做什么?

当我得到数组后,我可以更改一些代码,并制作我自己的方法运行。所以我需要某种解决方案才能从这里获得:

$array = array(
    'argument_label' => 'value_label',
    'argument_name' => 'value_name',
    'argument_id' => 'value_id'
)

到这里:

notArrayArgument('value_id', 'value_label', 'value_name');

或在这里:

notArrayArgument($array['argument_id'], $array['argument_label'], $array['argument_name']);

有什么问题?

  1. 这不是模板。变量个数总是不一样,名字总是不一样,有的传,有的不传。
  2. 它应该工作得非常快...
  3. 以正确的顺序调用方法参数。数组可以排序、不排序或随机排序,而方法中的参数总是以相同的顺序排列。数组应该重新排序以匹配方法参数顺序,然后调用方法。

我带来了什么?

  1. 我有一个使用 reflectionClass 的想法。我可以检查方法参数的名称,按顺序排列它们,重新排列数组并尝试调用此方法。但这是一个非常消耗资源的解决方案,因为我认为 reflectionClass 不是那么快。

  2. 解决方案使用提取?这会很棒。但是在提取之后,我需要在代码中使用确切的变量名称。而且我不了解它们,因为它们每次都不一样,我需要一种通用的方法。

  3. NEW(感谢评论):call_user_func_array()。这很棒,但它只适用于索引数组,因此这将是可能解决方案的最后但并非最不重要的一步。由于参数的顺序仍然未知...

这个问题有很好的语义、实用的解决方案吗?

我又看了一遍我的问题,希望能看清楚。如果没有,请post发表评论,我会尽力更好地描述问题。

考虑维护者的荣誉,但我认为简单性与良好的语义和实用主义一样重要。考虑一下:如果您不得不问如何编写这样的模式,那么 reader 显而易见的可能性有多大?我宁愿遇到我只能思考 "Yep, that's clear" 而不是 "Oh cool that's a really intricate and clever way of setting array defaults".

的代码

考虑到这一点,在我看来,在更适合 class 的情况下使用数组。您有一个 ID、一个标签和一个名称,它们肯定代表一个实体——正是 classes 的用途! 类 可以轻松设置默认值并提供 PHP 每个属性的文档。您可以拥有一个构造函数,该构造函数仅采用一个现有数组并 array_merge() 使用一组默认值对其进行处理。为了方便地进行反向转换,将对象转换为 PHP 中的数组会生成其属性的关联数组。

尝试使用 George Brighton 提到的 类。

如果您不能为某些遗留或库约束,您将不得不使用反射。不用太担心反射的性能类,很多框架都用它们来做请求路由。 您可以使用如下函数:

function arrayArgument($object, $method, $array)
{
    $arguments = [];
    $reflectionMethod = new ReflectionMethod(get_class($object), $method);
    foreach ($reflectionMethod->getParameters() as $parameter)
    {
        $arguments[] = isset($array[$parameter->name]) ? $array[$parameter->name] : $parameter->getDefaultValue();
    }
    call_user_func_array(array($object, $method), $arguments);
}

所以你可以

$instance = new MyClass();
arrayArgument($instance, 'notArrayArgument', ['name' => 'myname']);