На переходе к PHP 7.4 мне приходится иметь дело с различным поведением некоторых функций массива , как reset()
, current()
или end()
относительно ArrayObject. Следующий пример производит разные выходные данные:
<?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"
В версиях PHP до 7.4 вывод выглядит следующим образом:
string(1) "b"
string(1) "b"
A end($array->getArrayCopy())
создает уведомление, но может использоваться в качестве обходного пути, если используется с переменной.
Есть ли способ подражать поведению end()
с ArrayObject
или ArrayIterator
? ArrayObject может быть очень большим, итерация до конца может оказаться не лучшим решением.
$item = $array[count($array)-1];
. Не уверен, что это самое эффективное решение.Ответы:
В PHP 7.4 методы массива работают не с внутренним массивом, а с
ArrayObject
самим собой. Я суммировал два решения для этого.1. Получение внутреннего массива объекта.
2. Создание Фасада
ArrayObject
и добавление пользовательского метода end () в обновленный класс.источник
Вы можете сделать массивобъект массивом для получения ключей, затем использовать end для ключей, чтобы получить последний ключ.
Это не симпатичное решение, но оно работает.
Я предлагаю вам сделать это функцией, чтобы вы могли вызывать ее при необходимости.
https://3v4l.org/HTGYn
Как функция:
источник
array_keys()
решение с 3v4l.org/IaEMM/perf#output, но ему потребовалось на 20-30% больше памяти, чемend()
на простомgetArrayCopy()
3v4l.org/uYv59/perf#outputend
только ее, то вы можете создать класс-оболочку, который реализуетArrayAccess
и имеет дополнительную функцию, которая возвращаетend
внутренний закрытый массив, который будет работать.array_keys
? почему бы тебе просто не разыграть это прямо,$arr = (array) $array
а затем$end = end($arr)
Немного более быстрый подход без приведения или использования итератора состоял бы в том, чтобы вообще не использовать конструктор, а вместо этого использовать
append
метод, который создаст сам массив, и вы сможете использоватьend
этот массив позжеcount($array) - 1
в случае, если вы добавите другой массив позже, мы гарантируем, что$item
это всегда последний элемент в последнем добавленном массиве.источник
count()
может быть полезно в некоторых случаях, но ваш пример не сработает для чего-то подобногоnew \ArrayObject([123 => "a", 456 => "c"]);
append
вместо конструктора, использование append с вашим примером, безусловно, будет работать.$array->append([123 => "a", 456 => "c"]
count
что не для элементов вашего массива, а для многомерного массива, которыйappend
будет создан . Для вашего массива мы используемend
как обычно.append()
, я мог бы использоватьcount()
, это правильное решение. Это может работать сappend('a')
иappend('b')
. Ключом было бы запретить ассоциативные массивы, что возможно путем расширения ArrayObject.