skip to Main Content

On migrating to PHP 7.4 I have to deal with a different behavior of some array functions like reset(), current() or end() concerning ArrayObject. The following example produces different outputs:

<?php

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


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

With php 7.4 the output is:

bool(false)
string(1) "b"

On PHP versions before 7.4 the output is the following:

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

A end($array->getArrayCopy()) produces a notice, but might be a workaround if used with a variable.

Is there a way to emulate the behavior of end() with an ArrayObject or ArrayIterator? The ArrayObject could be very big, an iteration to the end might not be the best solution.

4

Answers


  1. You can make the arrayobject an array to get the keys then use end on the keys to get the last key.

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

    It’s not a pretty solution but it works.
    I suggest you make it a function so that you can call it when needed.

    https://3v4l.org/HTGYn

    As a function:

    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);
    
    Login or Signup to reply.
  2. A slightly faster approach without casting or using an iterator would be to not use the constructor in the first place, and instead use append method which will create an array itself and you can use end on that array later

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

    count($array) - 1 in case you append another array later, we make sure that $item is always the last element in the last appended array.

    Login or Signup to reply.
  3. From PHP 7.4 array methods don’t operate on internal array, but on ArrayObject itself. I summarized two solutions for that.

    1. Getting internal array of object.

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

    2. Creating Facade of ArrayObject and adding custom method end() to upgraded class.

    Login or Signup to reply.
  4. Came up with this approach.

    Should perform better than any of the above.

    • No casting to another variable using memory and CPU
    • Only one internal iterator.
    • Only one new variable, and it’s a reference to the item.
    class MyClass extends ArrayObject {
        public function last() {
            foreach ($this as $entity) {}
            return $entity ?? null;
        }
    }
    
    $array = new MyClass(["a", "b", "c"]);
    $item = $array->last();
    var_dump($item);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search