ArrayObject không hoạt động với end () trong PHP 7.4


9

Khi chuyển sang PHP 7.4, tôi phải xử lý một hành vi khác của một số hàm mảng như reset() , current()hoặc end()liên quan đến ArrayObject. Ví dụ sau đây tạo ra các đầu ra khác nhau:

<?php

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


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

Với php 7.4 , đầu ra là:

bool(false)
string(1) "b"

Trên các phiên bản PHP trước 7.4, đầu ra là như sau:

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

A end($array->getArrayCopy())tạo ra một thông báo, nhưng có thể là một cách giải quyết nếu được sử dụng với một biến.

Có cách nào để mô phỏng hành vi của end()với ArrayObjecthay ArrayIteratorkhông? ArrayObject có thể rất lớn, việc lặp lại đến cuối có thể không phải là giải pháp tốt nhất.


Một sự thay thế có thể là $item = $array[count($array)-1];. Không chắc chắn nếu đó là giải pháp hiệu quả nhất.
Patrick Q

2
Tôi muốn nói rằng nó đủ điều kiện là một lỗi PHP, chắc chắn không có gì trong danh sách thay đổi có thể gợi ý rằng đây là một thay đổi dự định trong 7.4
iainn

Kiểm tra trực tuyến: 3v4l.org/4MADI
0stone0

1
@PatrickQ nếu nó liên quan thì sao?
Andreas

4
@iainn điều này chắc chắn không phải là một lỗi - php.net/manual/en/...
u_mulder

Câu trả lời:


2

Từ PHP 7.4 các phương thức mảng không hoạt động trên mảng nội bộ, mà trên ArrayObjectchính nó. Tôi tóm tắt hai giải pháp cho điều đó.

1. Lấy mảng bên trong của đối tượng.

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

2. Tạo Mặt tiền ArrayObjectvà thêm phương thức tùy chỉnh end () vào lớp nâng cấp.


0

Bạn có thể tạo mảng cho một mảng để lấy các khóa sau đó sử dụng kết thúc trên các phím để lấy khóa cuối cùng.

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

var_dump($array[$end_key]);

Nó không phải là một giải pháp đẹp nhưng nó hoạt động.
Tôi đề nghị bạn làm cho nó một chức năng để bạn có thể gọi nó khi cần thiết.

https://3v4l.org/HTGYn

Là một chức năng:

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

Tôi không thấy sự khác biệt giữa cả hai câu trả lời khi tôi nhìn vào kết quả và usaqe trong câu hỏi. nếu sự khác biệt giải thích xin vui lòng
Dlk

1
Tôi đã thử nghiệm array_keys()giải pháp với 3v4l.org/IaEMM/perf#output nhưng nó cần thêm 20-30% bộ nhớ so với end()trên getArrayCopy() 3v4l.org/uYv59/perf#output
Trendfischer

1
@Trendfischer Nếu bộ nhớ là vấn đề và nếu bạn chỉ muốn sử dụng end, thì bạn có thể tạo một lớp bao bọc thực hiện ArrayAccessvà có một chức năng bổ sung trả về một endmảng riêng bên trong sẽ được vận hành.
vivek_23

1
@ vivek_23 nghe có vẻ là một câu trả lời hay
Trendfischer

3
Câu hỏi: mục đích của là array_keysgì? tại sao bạn không ném nó trực tiếp $arr = (array) $arrayvà sau đó$end = end($arr)
Mưa

0

Cách tiếp cận nhanh hơn một chút mà không cần truyền hoặc sử dụng trình lặp sẽ không sử dụng hàm tạo ở vị trí đầu tiên, và thay vào đó sử dụng appendphương thức sẽ tự tạo một mảng và bạn có thể sử dụng endtrên mảng đó sau

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

count($array) - 1trong trường hợp bạn nối thêm một mảng khác sau đó, chúng tôi đảm bảo rằng đó $itemluôn là phần tử cuối cùng trong mảng được nối thêm lần cuối.


1
Cảm ơn, giải pháp với count()có thể hữu ích trong một số trường hợp, nhưng ví dụ của bạn sẽ không hoạt động cho một cái gì đó như thế nàynew \ArrayObject([123 => "a", 456 => "c"]);
Trendfischer

@Trendfischer Tôi biết đó là lý do tại sao tôi sử dụng appendthay vì hàm tạo, sử dụng nối với ví dụ của bạn chắc chắn sẽ hoạt động. $array->append([123 => "a", 456 => "c"]
Mưa

@Trendfischer Xin lưu ý countkhông dành cho các thành phần của mảng của bạn, nó dành cho mảng đa chiều appendsẽ tạo. Đối với mảng của bạn, chúng tôi đang sử dụng endnhư bình thường.
Mưa

1
Tôi đánh giá cao ý định này, nhưng tôi thường không sử dụng ArrayObject như một sự thay thế đơn giản cho một mảng. Ví dụ trong câu hỏi là mẫu mực để chỉ ra vấn đề. Mặc dù nếu tôi chỉ sử dụng append(), tôi có thể sử dụng một count(), đó là giải pháp hợp lệ. Điều đó có thể làm việc với append('a')append('b'). Chìa khóa sẽ là không cho phép các mảng kết hợp có khả năng bằng cách mở rộng ArrayObject.
Trendfischer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.