Dotyczące migracji do PHP 7.4 mam do czynienia z innym zachowaniem pewnych funkcji, takich jak tablicy reset()
, current()
lub end()
dotycząca ArrayObject. Poniższy przykład przedstawia różne wyniki:
<?php
$array = new \ArrayObject(["a", "b"]);
$item = end($array);
var_dump($item);
$array = ["a", "b"];
$item = end($array);
var_dump($item);
W przypadku php 7.4 wynikiem jest:
bool(false)
string(1) "b"
W wersjach PHP wcześniejszych niż 7.4 wyniki są następujące:
string(1) "b"
string(1) "b"
A end($array->getArrayCopy())
generuje powiadomienie, ale może być obejściem, jeśli jest używane ze zmienną.
Czy istnieje sposób naśladowania zachowania end()
za pomocą ArrayObject
lub ArrayIterator
? ArrayObject może być bardzo duży, iteracja do końca może nie być najlepszym rozwiązaniem.
$item = $array[count($array)-1];
. Nie jestem pewien, czy jest to najbardziej wydajne rozwiązanie.Odpowiedzi:
Z PHP 7.4 metody tablicowe nie działają na wewnętrznej tablicy, ale na
ArrayObject
samej sobie. Podsumowałem dwa rozwiązania.1. Uzyskiwanie wewnętrznej tablicy obiektów.
2. Tworzenie fasady
ArrayObject
i dodawanie niestandardowej metody end () do ulepszonej klasy.źródło
Możesz ustawić obiekt tablicowy jako tablicę, aby uzyskać klucze, a następnie użyć klawisza end na klawiszach, aby uzyskać ostatni klucz.
To nie jest ładne rozwiązanie, ale działa.
Sugeruję, aby uczynić to funkcją, aby można było wywoływać ją w razie potrzeby.
https://3v4l.org/HTGYn
Jako funkcja:
źródło
array_keys()
rozwiązanie z 3v4l.org/IaEMM/perf#output, ale wymagało 20-30% więcej pamięci w porównaniu zend()
prostymgetArrayCopy()
3v4l.org/uYv59/perf#outputend
tylko używać , możesz utworzyć klasę opakowania, która implementujeArrayAccess
i ma dodatkową funkcję, która zwracaend
wewnętrzną prywatną tablicę, która byłaby obsługiwana.array_keys
? dlaczego nie rzucisz go bezpośrednio,$arr = (array) $array
a potem$end = end($arr)
Nieco szybszym podejściem bez rzucania lub używania iteratora byłoby nieużywanie konstruktora, a zamiast tego
append
metody, która utworzy samą tablicę i można z niej korzystaćend
późniejcount($array) - 1
w przypadku, gdy później dodasz kolejną tablicę, upewniamy się, że$item
jest to zawsze ostatni element w ostatniej dołączonej tablicy.źródło
count()
może być pomocne w niektórych przypadkach, ale twój przykład nie działałby dla czegoś takiegonew \ArrayObject([123 => "a", 456 => "c"]);
append
zamiast konstruktora, użycie append z twoim przykładem na pewno zadziała.$array->append([123 => "a", 456 => "c"]
count
nie dotyczy elementów tablicy, lecz wielowymiarowej tablicy,append
która utworzy. Do twojej tablicy używamyend
jak zwykle.append()
, mógłbym użyćcount()
, to jest prawidłowe rozwiązanie. To może działać zappend('a')
iappend('b')
. Kluczem byłoby wyłączenie tablic asocjacyjnych, co jest możliwe poprzez rozszerzenie ArrayObject.