Create Array of Objects in PHP
An array can contain a sequence of elements of different data types. From strings to integers to floats to objects.
In this post, we will discuss the different ways to how to create an array of objects in PHP.
Using [] syntax
We can use the short array syntax – [] – to create an array of objects by passing the object variable names to it.
Using array() method
We can simply use the array method to create an array of objects. All we need to do is simply pass objects as its arguments.
We can also use this same approach for class objects. By developing a class and specifying some of its features, we can produce objects. There will be some values for the class’s properties. The properties and values will finally combine to create a key-value pair in the array.
Here, we created Student class with 2 attributes, name and id .
Then created multiple objects and used array() to create array of objects in PHP.
Using stdClass Object
Another approach is to use of the stdClass object. By generating a PHP object of the stdClass , we may produce an array of objects. The PHP standard library of functions contains a definition for the stdClass . It is an empty class that can be used to typecast and set dynamic properties rather than being a base class for objects.
Here is an example of how to create an array of objects in PHP using the stdClass object:
The ArrayObject class
Properties of the object have their normal functionality when accessed as list (var_dump, foreach, etc.).
ArrayObject::ARRAY_AS_PROPS
Entries can be accessed as properties (read and write).
Table of Contents
- ArrayObject::append — Appends the value
- ArrayObject::asort — Sort the entries by value
- ArrayObject::__construct — Construct a new array object
- ArrayObject::count — Get the number of public properties in the ArrayObject
- ArrayObject::exchangeArray — Exchange the array for another one
- ArrayObject::getArrayCopy — Creates a copy of the ArrayObject
- ArrayObject::getFlags — Gets the behavior flags
- ArrayObject::getIterator — Create a new iterator from an ArrayObject instance
- ArrayObject::getIteratorClass — Gets the iterator classname for the ArrayObject
- ArrayObject::ksort — Sort the entries by key
- ArrayObject::natcasesort — Sort an array using a case insensitive «natural order» algorithm
- ArrayObject::natsort — Sort entries using a «natural order» algorithm
- ArrayObject::offsetExists — Returns whether the requested index exists
- ArrayObject::offsetGet — Returns the value at the specified index
- ArrayObject::offsetSet — Sets the value at the specified index to newval
- ArrayObject::offsetUnset — Unsets the value at the specified index
- ArrayObject::serialize — Serialize an ArrayObject
- ArrayObject::setFlags — Sets the behavior flags
- ArrayObject::setIteratorClass — Sets the iterator classname for the ArrayObject
- ArrayObject::uasort — Sort the entries with a user-defined comparison function and maintain key association
- ArrayObject::uksort — Sort the entries by keys using a user-defined comparison function
- ArrayObject::unserialize — Unserialize an ArrayObject
User Contributed Notes 22 notes
As you know ArrayObject is not an array so you can’t use the built in array functions. Here’s a trick around that:
Extend the ArrayObject class with your own and implement this magic method:
public function __call ( $func , $argv )
if (! is_callable ( $func ) || substr ( $func , 0 , 6 ) !== ‘array_’ )
throw new BadMethodCallException ( __CLASS__ . ‘->’ . $func );
>
return call_user_func_array ( $func , array_merge (array( $this -> getArrayCopy ()), $argv ));
>
?>
Now you can do this with any array_* function:
$yourObject -> array_keys ();
?>
— Don’t forget to ommit the first parameter — it’s automatic!
Note: You might want to write your own functions if you’re working with large sets of data.
There is a better explanation about the ArrayObject flags (STD_PROP_LIST and ARRAY_AS_PROPS) right here:
If you need the last key of your collection use:
array_key_last ( $this -> getArrayCopy ())
?>
In an extending class it could look like:
class Collection extends ArrayObject
public function lastKey (): int
return array_key_last ( $this -> getArrayCopy ());
>
>
?>
If you want to use any type safe collection:
class BookCollection extends Collection
public function add ( Book $book ) : void
$this -> offsetSet ( $book -> id , $book );
>
// note the return type «Book»
public function get ( int $bookId ) : Book
$this -> offsetGet ( $bookId );
>
>
?>
Generally variable $this can’t be used as an array within an object context. For example, following code piece would cause a fatal error:
class TestThis public function __set ( $name , $val ) $this [ $name ] = $val ;
>
public function __get ( $name ) return $this [ $name ];
>
>
$obj = new TestThis ();
$obj -> a = ‘aaa’ ;
echo $obj -> a . «\n» ;
?>
But things are different when $this is used in an ArrayObject object. e.g., following code piece are valid:
class TestArrayObject extends ArrayObject <
public function __set ( $name , $val ) $this [ $name ] = $val ;
>
public function __get ( $name ) return $this [ $name ];
>
>
$obj = new TestArrayObject ();
$obj -> a = ‘aaa’ ;
echo $obj -> a . «\n» ;
?>
I found the description of STD_PROP_LIST a bit vague, so I put together a simple demonstration to show its behavior:
$a = new ArrayObject (array(), ArrayObject :: STD_PROP_LIST );
$a [ ‘arr’ ] = ‘array data’ ;
$a -> prop = ‘prop data’ ;
$b = new ArrayObject ();
$b [ ‘arr’ ] = ‘array data’ ;
$b -> prop = ‘prop data’ ;
// ArrayObject Object
// (
// [prop] => prop data
// )
print_r ( $a );
// ArrayObject Object
// (
// [arr] => array data
// )
print_r ( $b );
// Example STD_PROP_LIST and ARRAY_AS_PROP combined
$ao = new ArrayObject ();
$ao -> setFlags ( ArrayObject :: STD_PROP_LIST | ArrayObject :: ARRAY_AS_PROPS );
$ao -> prop = ‘prop data’ ;
$ao [ ‘arr’ ] = ‘array data’ ;
ArrayObject Object
(
[storage:ArrayObject:private] => Array
(
[prop] => prop data
[arr] => array data
)
I don’t believe the same performance is true since PHP 5.3. Using the same fill, read_key and foreach approach on both native arrays and ArrayObjects with 10000 keys I get the following
array() fill 0.013101
array() read 0.008685
array() foreach 0.004319
ArrayObject fill 0.014136
ArrayObject read 0.010003
ArrayObject foreach 3.454612
array() fill 0.010395
array() read 0.005933
array() foreach 0.001903
ArrayObject fill 0.010598
ArrayObject read 0.006387
ArrayObject foreach 0.003451
This was the code I used for both, an array or ArrayObject is passed into each of the functions. Again PEAR::Benchmark was used to get the results.
If you want to use built-in array function with ArrayObject, store the iterator instance and return the value as reference in offsetGet.
$this -> iterator = $this -> getIterator ();
parent :: __construct ( $data );
>
To implement array-style appending (e.g. «$object[] = ‘foo’;») in your own class implementing the ArrayAccess _interface_, all you need do is check if the key passed to your implementation of offsetSet() is NULL. Something like the following.
class MyArrayObject implements ArrayAccess
/**
* @see ArrayAccess::offsetSet()
*/
public function offsetSet ( $p_key , $p_value ) if ( is_null ( $p_key )) $this -> aValue [] = $p_value ;
>
else $this -> aValue [ $p_key ] = $p_value ;
>
>
If you plan to derive your own class from ArrayObject, and wish to maintain complete ArrayObject functionality (such as being able to cast to an array), it is necessary to use ArrayObject’s own private property «storage».
Since that is impossible to do directly, you must use ArrayObject’s offset methods to manipulate it indirectly.
As a side benefit, this means you inherit all the iteration and other functions in complete working order.
This may sound obvious to someone who has never implemented their own ArrayObject class. but it is far from so.
class MyArrayObject extends ArrayObject <
static $debugLevel = 2 ;
static public function sdprintf () <
if (static:: $debugLevel > 1 ) <
call_user_func_array ( «printf» , func_get_args ());
>
>
public function offsetGet ( $name ) <
self :: sdprintf ( «%s(%s)\n» , __FUNCTION__ , implode ( «,» , func_get_args ()));
return call_user_func_array (array( parent , __FUNCTION__ ), func_get_args ());
>
public function offsetSet ( $name , $value ) <
self :: sdprintf ( «%s(%s)\n» , __FUNCTION__ , implode ( «,» , func_get_args ()));
return call_user_func_array (array( parent , __FUNCTION__ ), func_get_args ());
>
public function offsetExists ( $name ) <
self :: sdprintf ( «%s(%s)\n» , __FUNCTION__ , implode ( «,» , func_get_args ()));
return call_user_func_array (array( parent , __FUNCTION__ ), func_get_args ());
>
public function offsetUnset ( $name ) <
self :: sdprintf ( «%s(%s)\n» , __FUNCTION__ , implode ( «,» , func_get_args ()));
return call_user_func_array (array( parent , __FUNCTION__ ), func_get_args ());
>
>
$mao = new MyArrayObject ();
$mao [ «name» ] = «bob» ;
$mao [ «friend» ] = «jane» ;
print_r ((array) $mao );
offsetSet(name,bob)
offsetSet(friend,jane)
Array
(
[name] => bob
[friend] => jane
) */
?>
If you wish to use the «Array as Properties» flag, you simply need to include this in your constructor:
This will allow you to do things such as the below example, without overriding __get or __set .
$mao -> name = «Phil» ;
echo $mao [ «name» ]; /* Outputs «Phil» */
?>
Php new object in array
// Before php 5.4
$array = array(1,2,3);
// since php 5.4 , short syntax
$array = [1,2,3];
// I recommend using the short syntax if you have php version >= 5.4
Used to creating arrays like this in Perl?
Looks like we need the range() function in PHP:
$array = array_merge (array( ‘All’ ), range ( ‘A’ , ‘Z’ ));
?>
You don’t need to array_merge if it’s just one range:
There is another kind of array (php>= 5.3.0) produced by
$array = new SplFixedArray(5);
Standard arrays, as documented here, are marvellously flexible and, due to the underlying hashtable, extremely fast for certain kinds of lookup operation.
Supposing a large string-keyed array
$arr=[‘string1’=>$data1, ‘string2’=>$data2 etc. ]
when getting the keyed data with
php does *not* have to search through the array comparing each key string to the given key (‘string1’) one by one, which could take a long time with a large array. Instead the hashtable means that php takes the given key string and computes from it the memory location of the keyed data, and then instantly retrieves the data. Marvellous! And so quick. And no need to know anything about hashtables as it’s all hidden away.
However, there is a lot of overhead in that. It uses lots of memory, as hashtables tend to (also nearly doubling on a 64bit server), and should be significantly slower for integer keyed arrays than old-fashioned (non-hashtable) integer-keyed arrays. For that see more on SplFixedArray :
Unlike a standard php (hashtabled) array, if you lookup by integer then the integer itself denotes the memory location of the data, no hashtable computation on the integer key needed. This is much quicker. It’s also quicker to build the array compared to the complex operations needed for hashtables. And it uses a lot less memory as there is no hashtable data structure. This is really an optimisation decision, but in some cases of large integer keyed arrays it may significantly reduce server memory and increase performance (including the avoiding of expensive memory deallocation of hashtable arrays at the exiting of the script).
When creating arrays , if we have an element with the same value as another element from the same array, we would expect PHP instead of creating new zval container to increase the refcount and point the duplicate symbol to the same zval. This is true except for value type integer.
Example:
$arr = [‘bebe’ => ‘Bob’, ‘age’ => 23, ‘too’ => 23 ];
xdebug_debug_zval( ‘arr’ );
(refcount=2, is_ref=0)
array (size=3)
‘bebe’ => (refcount=1, is_ref=0)string ‘Bob’ (length=3)
‘age’ => (refcount=0, is_ref=0)int 23
‘too’ => (refcount=0, is_ref=0)int 23
but :
$arr = [‘bebe’ => ‘Bob’, ‘age’ => 23, ‘too’ => ’23’ ];
xdebug_debug_zval( ‘arr’ );
(refcount=2, is_ref=0)
array (size=3)
‘bebe’ => (refcount=1, is_ref=0)string ‘Bob’ (length=3)
‘age’ => (refcount=0, is_ref=0)int 23
‘too’ => (refcount=1, is_ref=0)string ’23’ (length=2)
or :
$arr = [‘bebe’ => ‘Bob’, ‘age’ => [1,2], ‘too’ => [1,2] ];
xdebug_debug_zval( ‘arr’ );
(refcount=2, is_ref=0)
array (size=3)
‘bebe’ => (refcount=1, is_ref=0)string ‘Bob’ (length=3)
‘age’ => (refcount=2, is_ref=0)
array (size=2)
0 => (refcount=0, is_ref=0)int 1
1 => (refcount=0, is_ref=0)int 2
‘too’ => (refcount=2, is_ref=0)
array (size=2)
0 => (refcount=0, is_ref=0)int 1
1 => (refcount=0, is_ref=0)int 2
This function makes (assoc.) array creation much easier:
function arr (. $array )< return $array ; >
?>
It allows for short syntax like:
$arr = arr ( x : 1 , y : 2 , z : 3 );
?>
Instead of:
$arr = [ «x» => 1 , «y» => 2 , «z» => 3 ];
// or
$arr2 = array( «x» => 1 , «y» => 2 , «z» => 3 );
?>
Sadly PHP 8.2 doesn’t support this named arguments in the «array» function/language construct.