ArrayObject tidak bekerja dengan end () di PHP 7.4

9

Pada migrasi ke PHP 7.4 saya harus berurusan dengan perilaku yang berbeda dari beberapa fungsi array seperti reset(), current()atau end()mengenai ArrayObject. Contoh berikut menghasilkan output yang berbeda:

<?php

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


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

Dengan php 7.4 hasilnya adalah:

bool(false)
string(1) "b"

Pada versi PHP sebelum 7.4 output adalah sebagai berikut:

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

A end($array->getArrayCopy())menghasilkan pemberitahuan, tetapi mungkin merupakan solusi jika digunakan dengan variabel.

Apakah ada cara untuk meniru perilaku end()dengan ArrayObjectatau ArrayIterator? ArrayObject bisa jadi sangat besar, iterasi sampai akhir mungkin bukan solusi terbaik.

Trendfischer
sumber
Sebuah alternatif bisa jadi $item = $array[count($array)-1];. Tidak yakin apakah itu solusi yang paling efisien.
Patrick Q
2
Saya akan mengatakan bahwa memenuhi syarat sebagai bug PHP, pasti tidak ada di changelog yang akan menyarankan ini adalah perubahan yang dimaksudkan di 7.4
iainn
Uji secara online: 3v4l.org/4MADI
0stone0
1
@ Patrickrick bagaimana jika asosiatif?
Andreas
4
@ iainn ini jelas bukan bug - php.net/manual/en/…
u_mulder

Jawaban:

2

Dari PHP 7.4 metode array tidak beroperasi pada array internal, tetapi pada ArrayObjectdirinya sendiri. Saya merangkum dua solusi untuk itu.

1. Mendapatkan array internal objek.

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

2. Membuat Fasad ArrayObjectdan menambahkan metode akhir khusus () ke kelas yang ditingkatkan.

Tajniak
sumber
0

Anda dapat membuat arrayobject sebuah array untuk mendapatkan kunci lalu gunakan akhir pada tombol untuk mendapatkan kunci terakhir.

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

var_dump($array[$end_key]);

Ini bukan solusi yang cantik tetapi berhasil.
Saya sarankan Anda menjadikannya fungsi sehingga Anda dapat memanggilnya saat dibutuhkan.

https://3v4l.org/HTGYn

Sebagai fungsi:

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);
Andreas
sumber
Saya tidak melihat perbedaan antara kedua jawaban ketika saya melihat hasilnya dan menggunakan pertanyaan. jika perbedaannya tolong jelaskan
Dlk
1
Saya telah menguji array_keys()solusinya dengan 3v4l.org/IaEMM/perf#output tetapi membutuhkan 20-30% lebih banyak pada memori dibandingkan dengan end()pada getArrayCopy() 3v4l.org/uYv59/perf#output
Trendfischer
1
@ Trendfischer Jika memori adalah masalah dan jika Anda hanya ingin menggunakan end, maka Anda dapat membuat kelas pembungkus yang mengimplementasikan ArrayAccessdan memiliki fungsi tambahan yang mengembalikan sebuah endarray privat internal yang akan dioperasikan.
vivek_23
1
@ vivek_23 sepertinya jawaban yang bagus
Trendfischer
3
Pertanyaan: apa tujuannya array_keys? kenapa tidak Anda hanya dilemparkan langsung $arr = (array) $arraydan kemudian$end = end($arr)
Hujan
0

Pendekatan yang sedikit lebih cepat tanpa casting atau menggunakan iterator adalah untuk tidak menggunakan konstruktor di tempat pertama, dan alih-alih menggunakan appendmetode yang akan membuat array itu sendiri dan Anda dapat menggunakan endarray itu nanti

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

count($array) - 1jika Anda menambahkan array lain nanti, kami memastikan bahwa $itemselalu elemen terakhir dalam array ditambahkan terakhir.

Hujan
sumber
1
Terima kasih, solusi dengan count()mungkin membantu dalam beberapa kasus, tetapi contoh Anda tidak akan bekerja untuk sesuatu seperti ininew \ArrayObject([123 => "a", 456 => "c"]);
Trendfischer
@ Trendfischer Saya tahu itu sebabnya saya menggunakan appendbukannya konstruktor, menggunakan menambahkan dengan contoh Anda pasti akan berhasil. $array->append([123 => "a", 456 => "c"]
Hujan
@ Trendfischer Harap dicatat countbukan untuk elemen array Anda, itu untuk array multidimensi yang appendakan dibuat. Untuk array Anda, kami menggunakan endseperti biasa.
Hujan
1
Saya menghargai niatnya, tetapi saya biasanya tidak menggunakan ArrayObject sebagai pengganti sederhana untuk array. Contoh dalam pertanyaan adalah contoh untuk menunjukkan masalahnya. Meskipun jika saya hanya menggunakan append(), saya bisa menggunakan count(), itu adalah solusi yang valid. Itu bisa bekerja dengan append('a')dan append('b'). Kuncinya adalah untuk melarang array asosiatif yang merupakan kemungkinan dengan memperluas ArrayObject.
Trendfischer