我觉得这很有意思! :)
我得到了什么?
在我在某些对象的某个级别上使用的应用程序(并不重要)我得到一个数组,例如:
$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']);
有什么问题?
我带来了什么?
我有一个使用 reflectionClass 的想法。我可以检查方法参数的名称,按顺序获取它们,重新排序数组并尝试调用此方法。但这是一个非常资源化的解决方案,因为我认为reflectionClass不是那么快。
使用提取的解决方案?这会很棒。但是在提取之后,我需要在代码中使用确切的变量名。而且每次他们不同时我都不知道他们,我需要一种普遍的方法。
新(请注释):call_user_func_array()。它很棒,但它只适用于索引数组,所以这将是可能解决方案的最后但并非最不重要的一步。由于论证的顺序仍然未知......
这个问题是否有一个很好的语义,实用的解决方案?
我再次阅读了我的问题,希望能够清楚地理解。如果没有,请发表评论,我会尽力更好地描述问题。
答案 0 :(得分:2)
Kudos考虑维护者,但我认为简单与良好的语义和实用主义同样重要。考虑一下:如果你不得不问如何编写这样一个模式,那么它对读者来说有什么可能是显而易见的?我更愿意遇到代码,我可以认为“是的,这是明确的”而不是“哦,很酷,这是一个非常复杂和聪明的设置数组默认值的方式”。
考虑到这一点,在我看来,数组正在更适合某个类的情况下使用。你有一个id,一个标签和一个名字,它肯定代表一个实体 - 确切地说是什么类!类可以很容易地设置默认值并在每个属性上提供PHPDoc。你可以有一个构造函数,它只需要一个现有的数组,array_merge()
就可以得到一个默认数组。对于反向转换,方便的是,在PHP中将对象转换为数组会产生其属性的关联数组。
答案 1 :(得分:1)
尝试使用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']);