ArrayObject не працює з end () в PHP 7.4


9

При переході до 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"

Для версій PHP до 7.4 вихід виглядає наступним чином:

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

A end($array->getArrayCopy())видає повідомлення, але воно може бути вирішенням, якщо використовується зі змінною.

Чи є спосіб наслідувати поведінку end()за допомогою ArrayObjectабо ArrayIterator? ArrayObject може бути дуже великим, ітерація до кінця може бути не найкращим рішенням.


Альтернативою може бути $item = $array[count($array)-1];. Не впевнений, чи це найефективніше рішення.
Патрік Q

2
Я б сказав, що кваліфікується як помилка PHP, напевно нічого немає в
журналі

Перевірте це в Інтернеті: 3v4l.org/4MADI
0stone0

1
@PatrickQ, що робити, якщо це асоціативно?
Андреас

4
@iainn це точно не помилка - php.net/manual/en/…
u_mulder

Відповіді:


2

З PHP 7.4 Методи масивів не працюють на внутрішньому масиві, але і на ArrayObjectсебе. Я підсумував два варіанти для цього.

1. Отримання внутрішнього масиву об’єкта.

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

2. Створення фасаду ArrayObjectта додавання спеціального методу end () до оновленого класу.


0

Ви можете зробити масив об’єктним масивом, щоб отримати ключі, а потім використовувати кінець на клавішах, щоб отримати останній ключ.

$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);

Я не бачу різниці між обома відповідями, коли я дивлюся на результат і американське питання. якщо різниця поясніть, будь ласка
Dlk

1
Я тестував array_keys()рішення з 3v4l.org/IaEMM/perf#output, але йому потрібно 20-30% більше пам’яті порівняно з end()простим getArrayCopy() 3v4l.org/uYv59/perf#output
Trendfischer

1
@Trendfischer Якщо проблемою є пам'ять, і якщо ви хочете використовувати endлише її, ви можете створити клас обгортки, який реалізує ArrayAccessта має додаткову функцію, яка повертає endвнутрішній приватний масив, який би використовувався.
vivek_23

1
@ vivek_23 звучить як добра відповідь
Trendfischer

3
Питання: яка мета array_keys? чому б ти просто не кинув його безпосередньо, $arr = (array) $arrayа потім$end = end($arr)
Дощ

0

Трохи швидший підхід без кастингу або використання ітератора - це не використовувати конструктор в першу чергу, а замість цього використовувати appendметод, який створить сам масив, і ви зможете використовувати endцей масив пізніше

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

count($array) - 1якщо ви додасте інший масив пізніше, ми переконаємося, що $itemце завжди останній елемент в останньому доданому масиві.


1
Дякую, рішення у програмі count()може бути корисним у деяких випадках, але ваш приклад не працював би на щось подібнеnew \ArrayObject([123 => "a", 456 => "c"]);
Trendfischer

@Trendfischer Я знаю, що тому я використав appendзамість конструктора, використовуючи додаток із вашим прикладом, безумовно, спрацює. $array->append([123 => "a", 456 => "c"]
Дощ

@Trendfischer Зверніть увагу, countце не для елементів вашого масиву, а для багатовимірного масиву, який appendбуде створено. Для вашого масиву ми використовуємо, endяк завжди.
Дощ

1
Я ціную намір, але зазвичай не використовую ArrayObject як просту заміну масиву. Приклад у запитанні є зразковим, щоб показати проблему. Хоча, якщо я лише використовую append(), я міг би використовувати це count(), це вірне рішення. Це могло б працювати з append('a')і append('b'). Ключовим моментом було б забороняти асоціативні масиви, що є можливим шляхом розширення ArrayObject.
Trendfischer
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.