可能的解决方案是 PHP 反射 API。考虑到这一点,您可以读取一个类的公共属性并将它们与同一类的另一个实例的其他公共属性进行比较。
以下代码是公共类属性的简单对比。比较的基础是一个简单的值对象。
declare(strict_types=1);
namespace Marcel\Test;
use ReflectionClass;
use ReflectionProperty;
class Example
{
private string $propertyA;
public string $propertyB;
public string $propertyC;
public function getPropertyA(): string
{
return $this->propertyA;
}
public function setPropertyA(string $propertyA): self
{
$this->propertyA = $propertyA;
return $this;
}
public function getPropertyB(): string
{
return $this->propertyB;
}
public function setPropertyB($propertyB): self
{
$this->propertyB = $propertyB;
return $this;
}
public function getPropertyC(): string
{
return $this->propertyC;
}
public function setPropertyC($propertyC): self
{
$this->propertyC = $propertyC;
return $this;
}
public function __compare(Example $b, $filter = ReflectionProperty::IS_PUBLIC): bool
{
$reflection = new ReflectionClass($b);
$properties = $reflection->getProperties($filter);
$same = true;
foreach ($properties as $property) {
if (!property_exists($this, $property->getName())) {
$same = false;
}
if ($this->{$property->getName()} !== $property->getValue($b)) {
$same = false;
}
}
return $same;
}
}
Example 类的__compare 方法使用PHP Reflection API。首先,我们构建一个我们想要与当前实例进行比较的类的反射实例。然后我们请求我们想要比较的类的所有公共属性。如果实例中不存在公共属性或者该属性的值与我们要比较的对象中的不同,则该方法返回false,否则返回true。
一些例子。
$objectA = (new Example())
->setPropertyA('bla')
->setPropertyB('yadda')
->setPropertyC('bar');
$objectB = (new Example())
->setPropertyA('foo')
->setPropertyB('yadda')
->setPropertyC('bar');
$result = $objectA->__compare($objectB);
var_dump($result); // true
在此示例中,比较结果为 true,因为公共属性 PropertyB 和 PropertyC 在两个实例中都存在并且具有相同的值。请记住,只有当第二个实例是同一个类时,这种比较才有效。可以进一步旋转该解决方案,并根据其特征比较所有可能的对象。
数组过滤器示例
它是基于所示__compare 方法的in_array 函数的一种重建。
declare(strict_types=1);
namespace Marcel\Test;
class InArrayFilter
{
protected ArrayObject $data;
public function __construct(ArrayObject $data)
{
$this->data = $data;
}
public function contains(object $b)
{
foreach ($this->data as $object) {
if ($b->__compare($object)) {
return true;
}
}
return false;
}
}
这个过滤器类的作用类似于in_array 函数。它获取对象集合并检查集合中是否存在具有相同公共属性的对象。
结论
如果您希望此解决方案像 array_unique、array_search 或 ìn_array 一样运行,您必须编写自己的回调函数,以您希望获得结果的方式执行 __compare 方法。
这取决于要处理的数据量和回调方法的性能。应用程序可能会消耗更多内存,因此变得更慢。