Backend Development

PHP Spl Data Structures: SplFixedArray

PHP Spl Data Structures SplFixedArray

One of the most important data structures not many people knows about it which included in the Spl extension is SplFixedArray.

 

 

If we think of a way to store data temporarily in any programming language, the term “array” will come to us in the first place, but in programming languages such as Java, for example, there are alternative to arrays, such as Map and Set which can be used in specific scenarios such as the big data.

However in the PHP world, we always use the traditional array as a storage method. But did you know that the SPL extension has a type of data structure that is very similar to array, which is the SplFixedArray.

Class Terminology

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class SplFixedArray implements IteratorAggregate, ArrayAccess, Countable, JsonSerializable {
/* Methods */
public __construct(int $size = 0)
public count(): int
public current(): mixed
public static fromArray(array $array, bool $preserveKeys = true): SplFixedArray
public getSize(): int
public setSize(int $size): bool
public toArray(): array
...
...
...
}
class SplFixedArray implements IteratorAggregate, ArrayAccess, Countable, JsonSerializable { /* Methods */ public __construct(int $size = 0) public count(): int public current(): mixed public static fromArray(array $array, bool $preserveKeys = true): SplFixedArray public getSize(): int public setSize(int $size): bool public toArray(): array ... ... ... }
 class SplFixedArray implements IteratorAggregate, ArrayAccess, Countable, JsonSerializable {
      /* Methods */
      public __construct(int $size = 0)
      public count(): int
      public current(): mixed
      public static fromArray(array $array, bool $preserveKeys = true): SplFixedArray
      public getSize(): int
      public setSize(int $size): bool
      public toArray(): array

      ...
      ...
      ...
}

These are some of the methods that SplFixedArray provides and as demonstrated in the class structure, the SplFixedArray implements IteratorAggregate, ArrayAccess, Countable, JsonSerializable. From among these the IteratorAggragate interface which enable us to iterate over the SplFixedArray as a normal array as we will see below.

When you instantiate a new object of this class you must specify the $size through the constructor or can be set using the SplFixedArray::setSize($size) method.

Example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<?php
$array = new SplFixedArray(10); // initialize a fixed array of size 10
echo "<pre>";
echo $array->getSize() . "<br/>\n";
$array[0] = 2;
$array[1] = 100;
$array[5] = "Hello world";
var_dump($array);
echo "</pre>";
// output
10
object(SplFixedArray)#1 (10) {
[0]=>
int(2)
[1]=>
int(100)
[2]=>
NULL
[3]=>
NULL
[4]=>
NULL
[5]=>
string(11) "Hello world"
[6]=>
NULL
[7]=>
NULL
[8]=>
NULL
[9]=>
NULL
}
<?php $array = new SplFixedArray(10); // initialize a fixed array of size 10 echo "<pre>"; echo $array->getSize() . "<br/>\n"; $array[0] = 2; $array[1] = 100; $array[5] = "Hello world"; var_dump($array); echo "</pre>"; // output 10 object(SplFixedArray)#1 (10) { [0]=> int(2) [1]=> int(100) [2]=> NULL [3]=> NULL [4]=> NULL [5]=> string(11) "Hello world" [6]=> NULL [7]=> NULL [8]=> NULL [9]=> NULL }
<?php
$array = new SplFixedArray(10);        // initialize a fixed array of size 10 

echo "<pre>";
echo $array->getSize() . "<br/>\n";

$array[0] = 2;
$array[1] = 100;
$array[5] = "Hello world";

var_dump($array);
echo "</pre>";

// output
10


object(SplFixedArray)#1 (10) {
  [0]=>
  int(2)
  [1]=>
  int(100)
  [2]=>
  NULL
  [3]=>
  NULL
  [4]=>
  NULL
  [5]=>
  string(11) "Hello world"
  [6]=>
  NULL
  [7]=>
  NULL
  [8]=>
  NULL
  [9]=>
  NULL
}

Here i created a new instance of SplFixedArray which have a length of 10 items. You can retrieve the array size by calling $array->getSize(). After that i assigned some items to array using the index syntax as normal array and the other items of the array will have the value Null as shown above.

Any attempt to assign a value to an out of bounds index will through exception like these:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$array[12] = 10000;
// Fatal error: Uncaught RuntimeException: Index invalid or out of range in /index.php
$array[12] = 10000; // Fatal error: Uncaught RuntimeException: Index invalid or out of range in /index.php
$array[12] = 10000;

// Fatal error:  Uncaught RuntimeException: Index invalid or out of range in /index.php

For that you can extend the size of the array using the SplFixedArray::setSize($size) method:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$array->setSize(15);
$array[12] = 10000;
echo $array->getSize(); // 15
$array->setSize(15); $array[12] = 10000; echo $array->getSize(); // 15
$array->setSize(15);

$array[12] = 10000;

echo $array->getSize();     // 15

To access particular item in the array you can use the item index like the normal array as well.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
echo $array[12]; // 10000
echo $array[12]; // 10000
echo $array[12];    // 10000 

Any item that haven’t been assigned a value have the value null by default.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
echo $array[7]; // empty value
echo $array[7]; // empty value
echo $array[7];    // empty value

There is another way to write a value to specific index and read a value using:

  • SplFixedArray::offsetSet(index, value) 
  • SplFixedArray::offsetGet(index).
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$array->offsetSet(7, "New item");
echo $array->offsetGet(7);
// output
New item
$array->offsetSet(7, "New item"); echo $array->offsetGet(7); // output New item
$array->offsetSet(7, "New item");
echo $array->offsetGet(7);    

// output 
New item

Also to check the existence of specific index there is SplFixedArray::offsetExists(index):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if($array->offsetExists(7)) {
echo "exists";
} else {
echo "not exists";
}
if($array->offsetExists(7)) { echo "exists"; } else { echo "not exists"; }
if($array->offsetExists(7)) {
    echo "exists";
} else {
    echo "not exists";
}

The php isset() function can be used also to check the existence like in normal arrays:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
if(isset($array[7])) {
echo "exists";
} else {
echo "not exists";
}
// output
exists
if(isset($array[7])) { echo "exists"; } else { echo "not exists"; } // output exists
if(isset($array[7])) {
    echo "exists";
} else {
    echo "not exists";
}

// output
exists

You can convert the SplFixedArray to normal array using the toArray() method like so:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$normalArray = $array->toArray();
var_dump($normalArray);
// output
array(15) {
[0]=>
int(2)
[1]=>
int(100)
[2]=>
NULL
[3]=>
NULL
[4]=>
NULL
[5]=>
string(11) "Hello world"
[6]=>
NULL
[7]=>
string(8) "New item"
...
...
}
$normalArray = $array->toArray(); var_dump($normalArray); // output array(15) { [0]=> int(2) [1]=> int(100) [2]=> NULL [3]=> NULL [4]=> NULL [5]=> string(11) "Hello world" [6]=> NULL [7]=> string(8) "New item" ... ... }
$normalArray = $array->toArray();
var_dump($normalArray);

// output
array(15) {
  [0]=>
  int(2)
  [1]=>
  int(100)
  [2]=>
  NULL
  [3]=>
  NULL
  [4]=>
  NULL
  [5]=>
  string(11) "Hello world"
  [6]=>
  NULL
  [7]=>
  string(8) "New item"
  ...
  ...
}

In the same way to convert normal array to SplFixedArray we can use the static method fromArray($array):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$normalArray = [1, "foo", 2, "bar", false];
var_dump(SplFixedArray::fromArray($normalArray));
$normalArray = [1, "foo", 2, "bar", false]; var_dump(SplFixedArray::fromArray($normalArray));
$normalArray = [1, "foo", 2, "bar", false];
var_dump(SplFixedArray::fromArray($normalArray));

 

Iterating Over SplFixedArray

We can loop over the SplFixedArray using the foreach loop as in usual arrays:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
foreach ($array as $key => $value) {
echo "$key: $value\n<br/>";
}
// output
1: 100
2:
3:
4:
5: Hello world
6:
...
...
...
foreach ($array as $key => $value) { echo "$key: $value\n<br/>"; } // output 1: 100 2: 3: 4: 5: Hello world 6: ... ... ...
foreach ($array as $key => $value) {
    echo "$key: $value\n<br/>";
}

// output
1: 100

2: 

3: 

4: 

5: Hello world

6: 
...
...
...

 

Advantages of SplFixedArray

So far we have described some of the methods and the basic usage of SplFixedArray but we haven’t discussed about why to choose to work with SplFixedArray over normal array.

Using of SplFixedArray does matter when you are dealing with huge data i.e storing millions of data as SplFixedArray provide a greater performance boost. Benchmarks states that SplFixedArray speed greater than normal array by 15% to 30%.

To demonstrate this we can use the microtime() function:

For normal array

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$startTime = microtime(true);
$arr = [];
for($i=0; $i < 5000000; $i++) {
$arr[] = $i;
}
$endTime = microtime(true);
echo "<br/>\n Time taken: " . ($endTime - $startTime);
// output
Time taken: 0.22327208518982
$startTime = microtime(true); $arr = []; for($i=0; $i < 5000000; $i++) { $arr[] = $i; } $endTime = microtime(true); echo "<br/>\n Time taken: " . ($endTime - $startTime); // output Time taken: 0.22327208518982
$startTime = microtime(true);
$arr = [];
for($i=0; $i < 5000000; $i++) {
    $arr[] = $i;
}
$endTime = microtime(true);

echo "<br/>\n Time taken: " . ($endTime - $startTime);


// output
 Time taken: 0.22327208518982

For splfixedarray

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
$starttime = microtime(true);
$fixedArray = new SplFixedArray(5000000);
for($i=0; $i < $fixedArray->count(); $i++) {
$fixedArray[$i] = $i;
}
$endtime = microtime(true);
echo "<br/>\n Time taken: " . ($endtime - $starttime);
// output
Time taken: 0.19789695739746
$starttime = microtime(true); $fixedArray = new SplFixedArray(5000000); for($i=0; $i < $fixedArray->count(); $i++) { $fixedArray[$i] = $i; } $endtime = microtime(true); echo "<br/>\n Time taken: " . ($endtime - $starttime); // output Time taken: 0.19789695739746
$starttime = microtime(true);
$fixedArray = new SplFixedArray(5000000);
for($i=0; $i < $fixedArray->count(); $i++) {
    $fixedArray[$i] = $i;
}
$endtime = microtime(true);

echo "<br/>\n Time taken: " . ($endtime - $starttime);


// output
 Time taken: 0.19789695739746

As you see in the next benchmark test that the SplFixedArray takes lower than the normal array.

 

5 1 vote
Article Rating

What's your reaction?

Excited
1
Happy
0
Not Sure
1
Confused
0

You may also like

Subscribe
Notify of
guest


0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments