Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
class GenericCollection implements \IteratorAggregate, \ArrayAccess{
/**
* @var string
*/
private $type;
/**
* @var array
*/
private $items = [];
/**
* GenericCollection constructor.
*
* @param string $type
*/
public function __construct(string $type){
$this->type = $type;
}
/**
* @param $item
*
* @return bool
*/
protected function checkType($item): bool{
$type = $this->getType();
return $item instanceof $type;
}
/**
* @return string
*/
public function getType(): string{
return $this->type;
}
/**
* @param string $type
*
* @return bool
*/
public function isType(string $type): bool{
return $this->type === $type;
}
#region IteratorAggregate
/**
* @return \Traversable|$type
*/
public function getIterator(): \Traversable{
return new \ArrayIterator($this->items);
}
#endregion
#region ArrayAccess
/**
* @param mixed $offset
*
* @return bool
*/
public function offsetExists($offset){
return isset($this->items[$offset]);
}
/**
* @param mixed $offset
*
* @return mixed|null
*/
public function offsetGet($offset){
return isset($this->items[$offset]) ? $this->items[$offset] : null;
}
/**
* @param mixed $offset
* @param mixed $item
*/
public function offsetSet($offset, $item){
if(!$this->checkType($item)){
throw new \InvalidArgumentException('invalid type');
}
$offset !== null ? $this->items[$offset] = $item : $this->items[] = $item;
}
/**
* @param mixed $offset
*/
public function offsetUnset($offset){
unset($this->items[$offset]);
}
#endregion
}
<?php
class Item{
/**
* @var int
*/
public $id = null;
/**
* @var string
*/
public $data = null;
/**
* Item constructor.
*
* @param int $id
* @param string $data
*/
public function __construct(int $id, string $data){
$this->id = $id;
$this->data = $data;
}
}
<?php
class ItemCollection extends GenericCollection{
/**
* ItemCollection constructor.
*/
public function __construct(){
parent::__construct(Item::class);
}
/**
* @return \Traversable|Item[]
*/
public function getIterator(): \Traversable{
return parent::getIterator();
}
}
<?php
class StringCollection extends GenericCollection{
/**
* @var bool
*/
private $nullable = false;
/**
* StringCollection constructor.
*
* @param bool $nullable
*/
public function __construct(bool $nullable = false){
parent::__construct('string');
}
/**
* @param $item
*
* @return bool
*/
protected function checkType($item): bool{
return is_string($item) || ($this->nullable && $item === null);
}
/**
* @return \Traversable|string[]
*/
public function getIterator(): \Traversable{
return parent::getIterator();
}
}
<?php
class ExampleService{
/**
* @var ItemCollection
*/
private $items = null;
/**
* SomeService constructor.
*
* @param ItemCollection $items
*/
public function __construct(ItemCollection $items){
$this->items = $items;
}
/**
* @return void
*/
public function list(){
foreach($this->items as $item){
echo $item->data;
}
}
}
<?php
/**
* ItemCollection example
*/
$collection = new ItemCollection;
$collection[] = new Item(1, 'A');
$collection[] = new Item(2, 'B');
$collection[] = new Item(3, 'C');
$collection[] = 42; // InvalidArgumentException: invalid type
$service = new ExampleService($collection);
$service->list();
/**
* StringCollection example
*/
$strings = new StringCollection;
$strings[] = 'foo';
$strings[] = 'bar';
$strings[] = 1337; // InvalidArgumentException: invalid type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment