【问题标题】:PHP key => value array to method arguments (order?)PHP键=>值数组到方法参数(顺序?)
【发布时间】:2015-11-14 11:09:23
【问题描述】:

我觉得这很有趣!!! :)。


我有什么?

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

$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 对数组的工作不太好),这些问题让我发疯。此外,对于将来使用此代码的人来说,这是一场噩梦,那时我已经是一个“退休的书呆子”了。


我想要什么?

我想要一个这样的功能:

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 的想法。我可以检查方法参数的名称,按顺序获取它们,重新排序数组并尝试调用此方法。但这是相当消耗资源的解决方案,因为我认为反射类并没有那么快。

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

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

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

我再次阅读了我的问题,希望清楚明白。如果没有,请发表评论,我会尽力更好地描述问题。

【问题讨论】:

  • 谢谢评论。是的,这是一个不错的函数,但是: param_arr:要传递给回调的参数,作为 INDEXED 数组。它只使用索引数组...没有 key=>value 数组,所以问题仍然存在,因为我不知道我应该添加参数的顺序。如果它可以与 key=>value 数组一起使用,我会为这个发现获得 200 个 stackoverflow 点;)。

标签: php arrays methods arguments


【解决方案1】:

对维护者的思考值得称赞,但我认为简单性与良好的语义和实用主义一样重要。考虑一下:如果你不得不问如何编写这样的模式,那么它对读者来说显而易见的可能性有多大?我更愿意遇到我可以认为“是的,这很清楚” 的代码,而不是 “哦,酷,这是设置数组默认值的一种非常复杂而聪明的方法”

考虑到这一点,在我看来,数组被用于更适合类的情况。你有一个 id、一个标签和一个名字,它们肯定代表一个实体——这正是类的用途!类可以很容易地设置默认值并在它们的每个属性上提供 PHPDoc。你可以有一个构造函数,它只需要一个现有的数组和array_merge()s 它带有一组默认值。对于反向转换,在 PHP 中将对象转换为数组会很方便地生成其属性的关联数组。

【讨论】:

  • 很好的答案,非常感谢+1。我真的很盲目,没有看到这正是一个对象。我唯一坚持的是接受哪个答案......你介意我接受 mcq8 anser 吗?他在这里较新,并给出了一个很好的工作代码示例。老实说,我应该接受他们两个,或者一个都不接受:)。
【解决方案2】:

尝试使用 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']);

【讨论】:

  • 很棒的代码示例,来自我的 +1。我将决定接受哪个答案。谢谢你的时间! :)。
猜你喜欢
  • 1970-01-01
  • 2011-06-21
  • 2020-03-16
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
相关资源
最近更新 更多