【问题标题】:ArrayObject does not work with end() in PHP 7.4ArrayObject 在 PHP 7.4 中不能与 end() 一起使用
【发布时间】:2020-06-05 21:57:21
【问题描述】:

在迁移到 PHP 7.4 时,我必须处理一些数组函数的不同行为,例如与 ArrayObject 相关的 reset()current()end()。以下示例产生不同的输出:

<?php

$array = new \ArrayObject(["a", "b"]);
$item = end($array);
var_dump($item);


$array = ["a", "b"];
$item = end($array);
var_dump($item);

使用 php 7.4 的输出是:

bool(false)
string(1) "b"

在 7.4 之前的 PHP 版本中,输出如下:

string(1) "b"
string(1) "b"

end($array-&gt;getArrayCopy()) 会生成通知,但如果与变量一起使用,可能是一种解决方法。

有没有办法用ArrayObjectArrayIterator 模拟end() 的行为? ArrayObject 可能非常大,迭代到最后可能不是最佳解决方案。

【问题讨论】:

  • 另一种可能是$item = $array[count($array)-1];。不确定这是否是最有效的解决方案。
  • 我会说这是一个 PHP 错误,更新日志中肯定没有任何内容表明这是 7.4 中的预期更改
  • 在线测试:3v4l.org/4MADI
  • @PatrickQ 如果它是关联的怎么办?
  • @iainn 这绝对不是错误 - php.net/manual/en/…

标签: php php-7.4


【解决方案1】:

来自PHP 7.4 的数组方法不对内部数组进行操作,而是对ArrayObject 本身进行操作。为此,我总结了两种解决方案。

1.获取对象的内部数组。

$array = new \ArrayObject(["a", "b"]);
$item = end($array->getArrayCopy());

2. 创建ArrayObject 的Facade 并将自定义方法end() 添加到升级后的类。

【讨论】:

    【解决方案2】:

    您可以将 arrayobject 设为数组以获取键,然后在键上使用 end 以获取最后一个键。

    $array = new \ArrayObject(["a", "b"]);
    $keys = array_keys((array)$array);
    $end_key = end($keys);
    
    var_dump($array[$end_key]);
    

    这不是一个很好的解决方案,但它确实有效。
    我建议你把它做成一个函数,这样你就可以在需要的时候调用它。

    https://3v4l.org/HTGYn

    作为一个函数:

    function end_object($array){
        $keys = array_keys((array)$array);
        $end_key = end($keys);
        return $array[$end_key];
    }
    
    
    $array = new \ArrayObject(["a", "b"]);
    $item = end_object($array);
    var_dump($item);
    

    【讨论】:

    • 当我查看结果和有问题的 usaqe 时,我没有看到两个答案之间的区别。如有差异请说明
    • 另一个答案使用数组并将其转换为不是 OP 要求的对象。我使用 arrayObject 并将其转换为数组以从中获取键。
    • 我已经用3v4l.org/IaEMM/perf#output 测试了array_keys() 解决方案,但与end() 在简单的getArrayCopy() 3v4l.org/uYv59/perf#output 上相比,它需要多出20-30% 的内存
    • @Trendfischer 如果内存是问题,并且如果您只想使用end,那么您可以创建一个实现ArrayAccess 的包装类,并具有一个返回end 的附加函数将被操作的内部私有数组。
    • 问题:array_keys 的目的是什么?你为什么不直接投$arr = (array) $array然后$end = end($arr)
    【解决方案3】:

    在不强制转换或使用迭代器的情况下稍快的方法是首先不使用构造函数,而是使用append 方法,该方法将自行创建一个数组,您可以稍后在该数组上使用end

    $array = new \ArrayObject();
    $array->append(["a", "b"]);
    $item =  end($array[count($array) - 1]);
    var_dump($item);
    

    count($array) - 1 如果您稍后附加另一个数组,我们会确保 $item 始终是最后一个附加数组中的最后一个元素。

    【讨论】:

    • 谢谢,count() 的解决方案在某些情况下可能会有所帮助,但您的示例不适用于 new \ArrayObject([123 =&gt; "a", 456 =&gt; "c"]);
    • @Trendfischer 我知道这就是我使用 append 而不是构造函数的原因,在您的示例中使用 append 肯定会起作用。 $array-&gt;append([123 =&gt; "a", 456 =&gt; "c"]
    • @Trendfischer 请注意count 不是用于数组的元素,而是用于append 将创建的多维数组。对于您的阵列,我们照常使用end
    • 我很欣赏这个意图,但我通常不使用 ArrayObject 作为数组的简单替代品。问题中的示例是显示问题的示例。虽然如果我只使用append(),我可以使用count(),这是有效的解决方案。这可以与append('a')append('b') 一起使用。关键是通过扩展 ArrayObject 来禁止关联数组。
    猜你喜欢
    • 1970-01-01
    • 2013-01-19
    • 2012-04-02
    • 2018-03-26
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    相关资源
    最近更新 更多