ArrayObjectは、PHP 7.4のend()では機能しません


9

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];。それが最も効率的なソリューションであるかどうかはわかりません。
Patrick Q

2
これはPHPのバグと
みなさ

オンラインでテスト:3v4l.org/4MADI
0stone0

1
@PatrickQ連想型の場合はどうなりますか?
Andreas

4
@iainnこれは間違いなくバグではありません- php.net/manual/en/...
u_mulder

回答:


2

PHP 7.4の配列方法は、内部配列を処理しますが、上のいないArrayObject自分自身。そのための2つの解決策をまとめました。

1.オブジェクトの内部配列を取得します。

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

2.ArrayObjectアップグレードされたクラスにカスタムメソッドend()のファサードを作成して追加します。


0

arrayobjectを配列にしてキーを取得し、キーでendを使用して最後のキーを取得できます。

$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
私は3v4l.org/IaEMM/perf#outputでarray_keys()ソリューションをテストしましたが、単純な3v4l.org/uYv59/perf#outputと比較して、メモリに20〜30%多く必要でしたend()getArrayCopy()
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コンストラクタの代わりに使用した理由です、あなたの例でappendを使用することは間違いなく動作します。$array->append([123 => "a", 456 => "c"]
雨の

@Trendfischer 作成するcount多次元配列用の配列の要素ではないことに注意してくださいappend。アレイにはend通常どおり使用しています。
雨の

1
私はその意図に感謝しますが、通常はArrayObjectを配列の単純な置き換えとして使用しません。質問の例は、問題を示すための模範例です。を使用するだけならappend()、を使用することもできますがcount()、これは有効なソリューションです。append('a')とで動作しappend('b')ます。重要なのは、連想配列を禁止することです。これは、ArrayObjectを拡張することで可能性があります。
Trendfischer
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.