gpt4 book ai didi

PHP 5.3 魔术方法 __invoke

转载 作者:IT王子 更新时间:2023-10-28 23:48:40 25 4
gpt4 key购买 nike

本主题扩展至 When do/should I use __construct(), __get(), __set(), and __call() in PHP?其中谈到了 __construct__get__set 魔术方法。

从 PHP 5.3 开始,有一个名为 __invoke 的新魔术方法。 __invoke 方法在脚本尝试将对象作为函数调用时被调用。

现在我对这个方法进行了研究,人们把它比作 Java 方法 .run() - 见 Interface Runnable .

经过长时间的认真思考,我想不出你为什么会调用 $obj(); 而不是 $obj->function();

即使您正在迭代对象数组,您仍然会知道要运行的主函数名称。

__invoke 魔术方法也是 PHP 中“仅仅因为你可以,并不意味着你应该”快捷方式的另一个例子,或者在某些情况下这实际上是正确的做法?

最佳答案

__invoke 的使用当您需要 callable 时才有意义那必须保持一些内部状态。假设您要对以下数组进行排序:

$arr = [
['key' => 3, 'value' => 10, 'weight' => 100],
['key' => 5, 'value' => 10, 'weight' => 50],
['key' => 2, 'value' => 3, 'weight' => 0],
['key' => 4, 'value' => 2, 'weight' => 400],
['key' => 1, 'value' => 9, 'weight' => 150]
];

usort function 允许您使用某些函数对数组进行排序,非常简单。但是在这种情况下,我们想使用其内部数组 'value' 键对数组进行排序,可以这样做:

$comparisonFn = function($a, $b) {
return $a['value'] < $b['value'] ? -1 : ($a['value'] > $b['value'] ? 1 : 0);
};
usort($arr, $comparisonFn);

// ['key' => 'w', 'value' => 2] will be the first element,
// ['key' => 'w', 'value' => 3] will be the second, etc

现在也许你需要重新对数组进行排序,但是这次使用 'key' 作为目标键,需要重写函数:

usort($arr, function($a, $b) {
return $a['key'] < $b['key'] ? -1 : ($a['key'] > $b['key'] ? 1 : 0);
});

正如您所见,该函数的逻辑与前一个相同,但是由于需要使用不同的键进行排序,我们不能重用前一个。这个问题可以通过在 __invoke 方法中封装比较逻辑并定义要在其构造函数中使用的键的类来解决:

class Comparator {
protected $key;

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

public function __invoke($a, $b) {
return $a[$this->key] < $b[$this->key] ?
-1 : ($a[$this->key] > $b[$this->key] ? 1 : 0);
}
}

一个实现 __invoke 的 Class 对象,它是一个“可调用的”,它可以在函数可能存在的任何上下文中使用,所以现在我们可以简单地实例化 Comparator 对象并将它们传递给 usort 函数:

usort($arr, new Comparator('key')); // sort by 'key'

usort($arr, new Comparator('value')); // sort by 'value'

usort($arr, new Comparator('weight')); // sort by 'weight'

以下段落反射(reflect)了我的主观意见,因此,如果您愿意,现在可以停止阅读答案;):尽管前面的示例显示了 __invoke 的非常有趣的用法,这种情况很少见,我会避免使用它,因为它可以以非常令人困惑的方式完成,并且通常有更简单的实现替代方案。在同一排序问题中的一个替代示例是使用返回比较函数的函数:

function getComparisonByKeyFn($key) {
return function($a, $b) use ($key) {
return $a[$key] < $b[$key] ? -1 : ($a[$key] > $b[$key] ? 1 : 0);
};
}
usort($arr, getComparisonByKeyFn('weight'));
usort($arr, getComparisonByKeyFn('key'));
usort($arr, getComparisonByKeyFn('value'));

虽然这个例子需要与 lambdas | closures | anonymous functions 更亲密一些。它更加简洁,因为它不会创建一个完整的类结构来存储外部值。

关于PHP 5.3 魔术方法 __invoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/888064/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com