ArrayObject non funziona con end () in PHP 7.4


9

Sulla migrazione a PHP 7.4 devo affrontare un diverso comportamento di alcune funzioni di matrice come reset(), current()o end()relativa ArrayObject. L'esempio seguente produce output diversi:

<?php

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


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

Con php 7.4 l'output è:

bool(false)
string(1) "b"

Nelle versioni PHP precedenti alla 7.4 l'output è il seguente:

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

A end($array->getArrayCopy())produce un avviso, ma potrebbe essere una soluzione alternativa se utilizzato con una variabile.

C'è un modo per emulare il comportamento di end()con un ArrayObjecto ArrayIterator? ArrayObject potrebbe essere molto grande, un'iterazione fino alla fine potrebbe non essere la soluzione migliore.


Un'alternativa potrebbe essere $item = $array[count($array)-1];. Non sono sicuro che sia la soluzione più efficiente.
Patrick Q,

2
Direi che si qualifica come un bug di PHP, non c'è assolutamente nulla nel
log delle


1
@PatrickQ e se fosse associativo?
Andreas,

4
@iainn questo non è sicuramente un bug - php.net/manual/en/...
u_mulder

Risposte:


2

Da PHP 7.4 i metodi dell'array non funzionano sull'array interno, ma su ArrayObjectse stesso. Ho riassunto due soluzioni per questo.

1. Ottenere array interno di oggetti.

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

2. Creazione della facciata ArrayObjecte aggiunta del metodo personalizzato end () alla classe aggiornata.


0

È possibile rendere l'arrayobject un array per ottenere le chiavi, quindi utilizzare end sui tasti per ottenere l'ultima chiave.

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

var_dump($array[$end_key]);

Non è una soluzione carina ma funziona.
Ti suggerisco di renderlo una funzione in modo da poterlo chiamare quando necessario.

https://3v4l.org/HTGYn

Come una funzione:

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

Non vedo la differenza tra entrambe le risposte quando guardo il risultato e usaqe in questione. se la differenza spiega per favore
Dlk il

1
Ho testato la array_keys()soluzione con 3v4l.org/IaEMM/perf#output ma aveva bisogno del 20-30% in più di memoria rispetto a un end()semplice getArrayCopy() 3v4l.org/uYv59/perf#output
Trendfischer

1
@Trendfischer Se la memoria è il problema e se si desidera utilizzare endsolo, è possibile creare una classe wrapper che implementa ArrayAccesse dispone di una funzione aggiuntiva che restituisce un endarray privato interno che verrebbe gestito.
vivek_23,

1
@ vivek_23 sembra una buona risposta
Trendfischer,

3
Domanda: qual è lo scopo array_keys? perché non lo lanci direttamente $arr = (array) $arraye poi$end = end($arr)
Rain,

0

Un approccio leggermente più veloce senza cast o utilizzo di un iteratore sarebbe quello di non utilizzare il costruttore in primo luogo, e utilizzare invece il appendmetodo che creerà un array stesso e sarà possibile utilizzarlo endin un secondo momento

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

count($array) - 1nel caso in cui aggiungi un altro array in un secondo momento, ci assicuriamo che $itemsia sempre l'ultimo elemento nell'ultimo array aggiunto.


1
Grazie, la soluzione con count()potrebbe essere utile in alcuni casi, ma il tuo esempio non funzionerebbe per qualcosa di similenew \ArrayObject([123 => "a", 456 => "c"]);
Trendfischer

@Trendfischer So che è per questo che ho usato al appendposto del costruttore, usando append con il tuo esempio sicuramente funzionerà. $array->append([123 => "a", 456 => "c"]
Pioggia il

@Trendfischer Nota che countnon è per gli elementi dell'array, ma per l'array multidimensionale che appendcreerà. Per il tuo array stiamo usando endcome al solito.
Pioggia il

1
Apprezzo l'intenzione, ma di solito non uso un ArrayObject come semplice sostituto di un array. L'esempio nella domanda è esemplare per mostrare il problema. Anche se se solo usassi append(), potrei usare una count()soluzione valida. Potrebbe funzionare con append('a')e append('b'). La chiave sarebbe quella di non consentire le matrici associative che è una possibilità estendendo ArrayObject.
Trendfischer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.