数组去重的结果

3
在处理项目中的DateTime时,如果使用array_unique来处理对象元素组成的数组,可能会出现重复问题(仅限于DateTime)。请参见以下代码:
class simpleClass
{
    public $dt;

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

$dateObj = new simpleClass(new DateTime);
$std = new stdClass;
$arr = [$dateObj, $dateObj, $std, $std, $std, $std];

var_dump(array_unique($arr, SORT_REGULAR));

预期有1个日期对象元素,但实际上有2个


2
有一些解决方法:https://dev59.com/lXE95IYBdhLWcg3wKqyq - Lajos Veres
你看,使用Datetime对象时出现了一个问题。 - sergio
2个回答

1

函数 array_unique() 将比较字符串,因此对象将被转换为字符串。解决方法是使用 __toString() 魔术方法返回完整的日期标识符:

class simpleClass
{
    public $dt;

    function __construct(DateTime $dt) {
        $this->dt = $dt;
    }

    public function __toString() {
        return $this->dt->format('r');
    }

}

$dateObj1 = new simpleClass(new DateTime);
$dateObj2 = new simpleClass(new DateTime);
$dateObj3 = new simpleClass(new DateTime('today'));
$arr = [$dateObj1, $dateObj2, $dateObj3];

print_r(array_unique($arr));

演示.


嗯,但是你创建了三个对象的区别在于,我正在尝试找出我的问题原因,在我的项目中,我不能像你的示例那样随意创建对象。 - sergio
我发现了一个错误,但是无法找到其原因。 - sergio
@sergio:是的,你的例子表现得很奇怪,它应该抛出某种错误或通知,因为如果你将 $dateObj$std 强制转换为字符串,它会抛出 Catchable fatal error: Object of class CLASSNAME could not be converted to string,但当你在函数 array_unique() 中使用它们时,内部强制转换为字符串,没有出现错误,输出结果很奇怪... - Glavić
嗯,这就是为什么我阅读了很多 PHP 文档,但并没有找到答案的原因。 - sergio
1
@sergio: 然而,array_unique() 可以用于字符串。只有当(string)$elem1===(string)$elem2时,两个元素才被视为相等。换句话说:当字符串表示相同时,将使用第一个元素。你正在将没有toString魔法方法的对象转换为字符串,这是一个大错误。 - Glavić

0

我还是不理解。使用以下代码设置数组:

$arr = [$dateObj, $dateObj, $std, $std];

返回:

array (size=2)
    0 => 
        object(simpleClass)[1]
            public 'dt' => 
              object(DateTime)[2]
                  public 'date' => string '2013-11-14 14:37:08' (length=19)
                  public 'timezone_type' => int 3
                  public 'timezone' => string 'Europe/Rome' (length=11)
    2 => 
       object(stdClass)[3]

这样看来,array_unique 似乎有效...


嗯,有些奇怪的行为。 - sergio
就像我所说的,如果对象不能转换为字符串,则无法使用函数 array_unique() 进行操作;结果会是不可预测的。查看演示 - Glavić
好的,好的,我只是在调查。在我的看法中,即使使用神奇的__toString()也不起作用。 - ilpaijin
@ilpaijin:你能否创建一个https://eval.in/的示例,其中__toString()无法工作吗?很难相信它不起作用。 - Glavić
1
@ilpaijin:从array_unique()函数中删除第二个参数SORT_REGULAR演示 - Glavić
哦,好的,那样也可以。我发现在手册中使用 SORT_STRING 标志可以正常工作,“SORT_REGULAR - 正常比较项目(不更改类型)”。 - ilpaijin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接