#native_company# #native_desc#
#native_cta#

Implementing PHP Collection Classes

By Octavia Andreea Anghel
on July 29, 2016

A Collection class is an OOP replacement for the traditional array data structure. As the name suggests, a collection can be seen as a container and can be described as a class designed for holding data of a specific type or any type.

Collections can be seen as more specialized arrays, so, practically, a Collection class should be able to make some simple array manipulation tasks such as sorting, counting arrays, adding or removing items, getting an element by its index and so on, as you will see in the Collection class from next section of this article.

This article will show you how to create a Collection class using different types of methods used to manipulate arrays and we will apply the Reflection mechanism over this class.

Creating the Collection class

As I mention above, a collection class needs to reveal methods that allow us to add, get, sort and remove items, list the size of the collection, check if a given object exists in the collection, checking if the collection is empty or not, setting an element by its key, etc.

To create a Collection class we need to implement two interfaces: ArrayAccess and Iterator interfaces, described next:

The ArrayAccess interface provide accessing objects as arrays for the purposes of setting, unsetting and retrieving data from it. To implement ArrayAccess you need to implement four methods:

   • ArrayAccess::offsetExists — Whether an offset exists

   • ArrayAccess::offsetGet — Offset to retrieve

   • ArrayAccess::offsetSet — Assign a value to the specified offset

   • ArrayAccess::offsetUnset — Unset an offset

The Iterator interface is an interface for external iterators or objects that can be iterated themselves internally.

To implement Iterator you need to implement five methods:

   • Iterator::current — Return the current element

   • Iterator::key — Return the key of the current element

   • Iterator::next — Move forward to next element

   • Iterator::rewind — Rewind the Iterator to the first element

   • Iterator::valid — Checks if current position is valid

Below is the Collection class that contains all the practical methods in order to work with arrays:

<?php

   class Collection implements Iterator, ArrayAccess {
        
        //The number of elements from the Collection
        public $length=0;

        //The array
        //public $array = array('12','5','60', '98', '8');       

       //Adding an object into a collection     
       function add($arg1,$arg2=false)  {
            if(!$arg2) {
                $this->array_elements[] = $arg1;
            } else {
                if (!array_key_exists($arg1,$this->array_elements)) {
                    $this->array_elements[$arg1] = $arg2;
                }
            }
            $this->count();		
            return $this ;
        }
  
        //Setting a value for a specified key of the array_elements
        function set($key,$item) {
	    if(isset($key)) {
		$this->array_elements[$key] = $item;
            } else {
		$this->array_elements[] = $item ;
	    }
            $this->count();
            return $this->get($key);
        }
          
        //Sorting the array by values
        function asort($flags=null) {
            asort($this->array_elements,$flags);
            return $this;
        }
       
        //Sorting the array by keys
        function ksort($flags=null) {
            ksort($this->array_elements,$flags);
            return $this;
        }

        //Sorting the array naturally
        function sort($flags=null) {
            sort($this->array_elements,$flags);
            return $this ;
        }
        
        //Getting the length of the array
        function count() { 
            $this->lenght = count($this->array_elements);
            return $this->lenght ;
        }        
        
        //Removing a specified kye
        function remove($key) {
            if (array_key_exists($key,$this->array_elements)) {
                unset($this->array_elements[$key]);
                $this->count();
                return $this;
            }
        }
       
        //Moving the cursor a step forward
        function next() {
            return next($this->array_elements) ;
        }

       //Cheking if the next element is valid
        function hasNext() {
            $this->next() ;
            $v = $this->valid() ;
            $this->back() ;
            return $v ;
        }
           
        //Moves the cursor a step back
        function back() {
            return prev($this->array_elements);
        }

        //Moves the cursor at start
        function rewind() {
            return reset($this->array_elements);
        }

        //Moves the cursor at the end
        function forward() {
            return end($this->array_elements);
        }

        //Getting the key from the pointed cursor
        function current() {
            return current($this->array_elements);
        }
    
      //Getting the current cursor of the key
      function currentKey() {
            return key($this->array_elements) ; 
        }
    
        //Getting the cursor of the key
        function key() {
            return $this->currentKey();
        }
        
        //Checking if the cursor is at a valid item
        function valid() {
            if(!is_null($this->key())) {
                return true;
            } else {
                return false ;
            }
        }
        
        //Returning object for given posistion
        function get($key) {
            return $this->array_elements[$key];
        }     

     	  //Checking if an offset exists using Array Access interface
        function offsetExists($offset) {
            return $this->exists($offset);
        }

        //Getting an element using Array Access interface
        function offsetGet($offset) {
            return $this->get($offset);
        }

        //Setting an element using Array Access interface
        function offsetSet($offset,$value) {
            return $this->set($offset, $value);
        } 
    
        //Removing element using Array Access interface
        function offsetUnset($offset) {
            return $this->remove($offset);
        }
	
        //Checking if the collection is empty or not
        function isEmpty() {
 	    if($this->count() < 1)
        	return true ;
	    else
            return false;
        }

        //Checking if a given object exists in collection
        function contains($obj) {
            foreach($this->array_elements as $element) {
                if($element === $obj) {
                    $this->rewind();
                    return true ;
                }
            }
            $this->rewind();
            return false ;
        }
    
        //Returning the first index of given object
        function indexOf($obj) {
            foreach($this->array_elements as $k=>$element) {
                if($element === $obj) {    			
                    $this->rewind();
                    return $k ;
                }
            }
            $this->rewind();
            return null ;
        }
    
        //Cutting the array to given size
        function trimToSize($size) {
            $t = array_chunk($this->array_elements,$size,true);
            $this->array_elements = $t[0];
            $this->count();
            return $this ;
        }   
    }

?> 

Testing the Collection class from above, using some of the most important methods in working with:

1. Adding a new entry into the collection:

$collection = new Collection($array);

$a=$collection->add('34');

print "<pre>";
print_r($a);
print "</pre>";

The output will be:

Collection Object
(
    [lenght] => 6
    [array_elements:Collection:private] => Array
        (
            [0] => 12
            [1] => 5
            [2] => 60
            [3] => 98
            [4] => 8
            [5] => 34
        )

) 

2. Checking if the collection is empty:

$collection = new Collection($array);

if($collection->isEmpty()){
	echo 'The collection is empty ';}
else 
	{echo 'The collection is not empty ';} 

The output will be:

The collection is not empty

3. Setting a value for the collection (in this case [2]=>1000)

$collection = new Collection($array);

$s=$collection->set('2','1000');

print "<pre>";
print_r($collection);
print "</pre>";

The output will be:

Collection Object
(
    [lenght] => 6
    [array_elements:Collection:private] => Array
        (
            [0] => 12
            [1] => 5
            [2] => 1000
            [3] => 98
            [4] => 8
            [5] => 34
        )

) 

4. Trimming the collection to a specified length (in our case 2):

$collection = new Collection($array);

$trimToSize=$collection->trimToSize(2);

print "<pre>";
print_r($trimToSize);
print "</pre>";

The output is:

Collection Object
(
    [lenght] => 2
    [array_elements:Collection:private] => Array
        (
            [0] => 12
            [1] => 5
        )

) 

5. Sorting the collection

$collection = new Collection($array);

//This function sorts an array. Elements will be arranged from lowest to highest when this function has completed.
$sortingCollection=$collection->sort();

//Sorts an array by key, maintaining key to data correlations
$sortingCollection=$collection->ksort();

//Sort an array and maintain index association
$sortingCollection=$collection->asort();

print "<pre>";
print_r($sortingCollection);
print "</pre>";

The output of this different collection sorting is:

sort()
----------------
Collection Object
(
    [lenght] => 5
    [array_elements:Collection:private] => Array
        (
            [0] => 5
            [1] => 8
            [2] => 12
            [3] => 60
            [4] => 98
        )

)

ksort()
----------------
Collection Object
(
    [lenght] => 5
    [array_elements:Collection:private] => Array
        (
            [0] => 12
            [1] => 5
            [2] => 60
            [3] => 98
            [4] => 8
        )

)

asort()
----------------
Collection Object
(
    [lenght] => 5
    [array_elements:Collection:private] => Array
        (
            [1] => 5
            [4] => 8
            [0] => 12
            [2] => 60
            [3] => 98
        )

) 

Applying the Reflection Mechanism Over the Collection Class

The next listing uses the Reflection mechanism to reveal all the methods of our Collection class using the ReflectionClass class. This class reports information about a class, such as interfaces, methods, constructor, properties, constants and so on. Learn more about the ReflectionClass methods.

In the listing below we will only use the getMethods() method:

<?php

include ('Collection.php');
$reflection = new ReflectionClass("Collection");

$methods = $reflection->getMethods();
echo "The following methods are available:".'<br/>';
	
print "<pre>";
print_r($methods);
print "</pre>";

?> 

The following methods are available:

Array
(
    [0] => ReflectionMethod Object
        (
            [name] => add
            [class] => Collection
        )

    [1] => ReflectionMethod Object
        (
            [name] => set
            [class] => Collection
        )

    [2] => ReflectionMethod Object
        (
            [name] => asort
            [class] => Collection
        )

    [3] => ReflectionMethod Object
        (
            [name] => ksort
            [class] => Collection
        )

    [4] => ReflectionMethod Object
        (
            [name] => sort
            [class] => Collection
        )

    [5] => ReflectionMethod Object
        (
            [name] => count
            [class] => Collection
        )

    [6] => ReflectionMethod Object
        (
            [name] => remove
            [class] => Collection
        )

    [7] => ReflectionMethod Object
        (
            [name] => next
            [class] => Collection
        )

    [8] => ReflectionMethod Object
        (
            [name] => hasNext
            [class] => Collection
        )

    [9] => ReflectionMethod Object
        (
            [name] => back
            [class] => Collection
        )

    [10] => ReflectionMethod Object
        (
            [name] => rewind
            [class] => Collection
        )

    [11] => ReflectionMethod Object
        (
            [name] => forward
            [class] => Collection
        )

    [12] => ReflectionMethod Object
        (
            [name] => current
            [class] => Collection
        )

    [13] => ReflectionMethod Object
        (
            [name] => currentKey
            [class] => Collection
        )

    [14] => ReflectionMethod Object
        (
            [name] => key
            [class] => Collection
        )

    [15] => ReflectionMethod Object
        (
            [name] => valid
            [class] => Collection
        )

    [16] => ReflectionMethod Object
        (
            [name] => get
            [class] => Collection
        )

    [17] => ReflectionMethod Object
        (
            [name] => offsetExists
            [class] => Collection
        )

    [18] => ReflectionMethod Object
        (
            [name] => offsetGet
            [class] => Collection
        )

    [19] => ReflectionMethod Object
        (
            [name] => offsetSet
            [class] => Collection
        )

    [20] => ReflectionMethod Object
        (
            [name] => offsetUnset
            [class] => Collection
        )

    [21] => ReflectionMethod Object
        (
            [name] => isEmpty
            [class] => Collection
        )

    [22] => ReflectionMethod Object
        (
            [name] => contains
            [class] => Collection
        )

    [23] => ReflectionMethod Object
        (
            [name] => indexOf
            [class] => Collection
        )

    [24] => ReflectionMethod Object
        (
            [name] => trimToSize
            [class] => Collection
        )

    [25] => ReflectionMethod Object
        (
            [name] => getIterator
            [class] => Collection
        )

) 

Conclusion

During this article you have seen how to create the Collection class (which implements the ArrayAccess and Iterator interfaces) that allow us to make use of the most handy methods, such as adding, removing and resizing of the collection.