Ao migrar para o PHP 7.4, eu tenho que lidar com um comportamento diferente de algumas funções de array como reset()
, current()
ou end()
relativas a ArrayObject. O exemplo a seguir produz saídas diferentes:
<?php
$array = new \ArrayObject(["a", "b"]);
$item = end($array);
var_dump($item);
$array = ["a", "b"];
$item = end($array);
var_dump($item);
Com o php 7.4, a saída é:
bool(false)
string(1) "b"
Nas versões do PHP anteriores à 7.4, a saída é a seguinte:
string(1) "b"
string(1) "b"
A end($array->getArrayCopy())
produz um aviso, mas pode ser uma solução alternativa se usado com uma variável.
Existe uma maneira de imitar o comportamento de end()
com um ArrayObject
ou ArrayIterator
? O ArrayObject pode ser muito grande, uma iteração até o final pode não ser a melhor solução.
$item = $array[count($array)-1];
. Não tenho certeza se essa é a solução mais eficiente.Respostas:
A partir do PHP 7.4, os métodos de array não operam em array interno, mas por
ArrayObject
si só. Resumi duas soluções para isso.1. Obtendo matriz interna de objeto.
2. Criando Fachada
ArrayObject
e adicionando o método personalizado end () à classe atualizada.fonte
Você pode fazer do array um objeto para obter as chaves e usar end nas teclas para obter a última chave.
Não é uma solução bonita, mas funciona.
Eu sugiro que você faça uma função para poder chamá-la quando necessário.
https://3v4l.org/HTGYn
Como uma função:
fonte
array_keys()
solução com 3v4l.org/IaEMM/perf#output, mas ela precisava de 20 a 30% a mais de memória em comparação com umaend()
simplesgetArrayCopy()
3v4l.org/uYv59/perf#outputend
apenas usá -lo, é possível criar uma classe de wrapper que implementeArrayAccess
e tenha uma função adicional que retorne umend
array interno interno que seria operado.array_keys
? por que você não o lança diretamente$arr = (array) $array
e depois$end = end($arr)
Uma abordagem um pouco mais rápida sem converter ou usar um iterador seria não usar o construtor em primeiro lugar e, em vez disso, usar o
append
método que criará uma matriz em si e você poderá usáend
-la posteriormentecount($array) - 1
caso você acrescente outra matriz posteriormente, garantimos que esse$item
seja sempre o último elemento da última matriz anexada.fonte
count()
pode ser útil em alguns casos, mas o seu exemplo não funcionaria para algo como istonew \ArrayObject([123 => "a", 456 => "c"]);
append
vez do construtor, usar o apêndice com seu exemplo definitivamente funcionará.$array->append([123 => "a", 456 => "c"]
count
não é para os elementos da sua matriz, é para a matriz multidimensional queappend
será criada. Para sua matriz, estamos usandoend
como de costume.append()
, poderia usar umacount()
solução válida. Isso poderia funcionar comappend('a')
eappend('b')
. A chave seria desabilitar matrizes associativas, o que é uma possibilidade, estendendo ArrayObject.