Lors de la migration vers PHP 7.4, je dois faire face à un comportement différent de certaines fonctions de tableau comme reset()
, current()
ou end()
concernant ArrayObject. L'exemple suivant produit différentes sorties:
<?php
$array = new \ArrayObject(["a", "b"]);
$item = end($array);
var_dump($item);
$array = ["a", "b"];
$item = end($array);
var_dump($item);
Avec php 7.4, la sortie est:
bool(false)
string(1) "b"
Sur les versions PHP antérieures à 7.4, la sortie est la suivante:
string(1) "b"
string(1) "b"
A end($array->getArrayCopy())
produit un avis, mais peut être une solution de contournement s'il est utilisé avec une variable.
Existe-t-il un moyen d'émuler le comportement de end()
avec ArrayObject
ou ArrayIterator
? ArrayObject peut être très volumineux, une itération à la fin n'est peut-être pas la meilleure solution.
$item = $array[count($array)-1];
. Je ne sais pas si c'est la solution la plus efficace.Réponses:
Depuis PHP 7.4 , les méthodes de tableau ne fonctionnent pas sur le tableau interne, mais sur
ArrayObject
lui-même. J'ai résumé deux solutions pour cela.1. Obtention d'un tableau d'objet interne.
2. Création de la façade
ArrayObject
et ajout de la méthode personnalisée end () à la classe mise à niveau.la source
Vous pouvez faire de arrayobject un tableau pour obtenir les clés, puis utiliser end sur les clés pour obtenir la dernière clé.
Ce n'est pas une jolie solution mais ça marche.
Je vous suggère d'en faire une fonction pour pouvoir l'appeler en cas de besoin.
https://3v4l.org/HTGYn
En tant que fonction:
la source
array_keys()
solution avec 3v4l.org/IaEMM/perf#output mais elle avait besoin de 20-30% de plus en mémoire par rapport àend()
un simplegetArrayCopy()
3v4l.org/uYv59/perf#outputend
uniquement, vous pouvez créer une classe wrapper qui implémenteArrayAccess
et avoir une fonction supplémentaire qui renvoie unend
du tableau privé interne qui serait exploité.array_keys
? pourquoi ne pas le lancer directement$arr = (array) $array
et ensuite$end = end($arr)
Une approche légèrement plus rapide sans transtypage ni utilisation d'un itérateur serait de ne pas utiliser le constructeur en premier lieu, et d'utiliser à la place une
append
méthode qui créera un tableau lui-même et que vous pourrez utiliserend
sur ce tableau plus tard.count($array) - 1
si vous ajoutez un autre tableau plus tard, nous nous assurons qu'il$item
s'agit toujours du dernier élément du dernier tableau ajouté.la source
count()
pourrait être utile dans certains cas, mais votre exemple ne fonctionnerait pas pour quelque chose comme çanew \ArrayObject([123 => "a", 456 => "c"]);
append
place du constructeur, utiliser append avec votre exemple fonctionnera certainement.$array->append([123 => "a", 456 => "c"]
count
n'est pas pour les éléments de votre tableau, c'est pour le tableau multidimensionnel quiappend
va créer. Pour votre tableau, nous utilisonsend
comme d'habitude.append()
, je pourrais utiliser uncount()
, c'est une solution valide. Cela pourrait fonctionner avecappend('a')
etappend('b')
. La clé serait de interdire les tableaux associatifs, ce qui est possible en étendant ArrayObject.