Implementing typed collections
For stricter type hinting and iterfaces it could be useful to implement typed collections to put your models and other same-typed classes into.
As an example, we'll assume we have a Post
class:
class Post
{
private $title;
public function __construct($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
A simple typed immutable collection could be implemented like the following:
class PostCollection implements \Countable, \IteratorAggregate
{
private $data;
public function __construct(array $data)
{
foreach ($data as $item) {
if (!$item instanceof Post) {
throw new \InvalidArgumentException('All items should be of Post class.');
}
}
$this->data = $data;
}
public function count()
{
return count($this->data);
}
public function getIterator()
{
return new \ArrayIterator($this->data);
}
}
That's it. Now you can use it like the following:
$data = [new Post('post1'), new Post('post 2')];
$collection = new PostCollection($data);
foreach ($collection as $post) {
echo $post->getTitle();
}
The main pro besides type checking in the constructor is about interfaces. With typed collections you may explicitly require a set of items of a certain class:
interface FeedGenerator
{
public function generateFromPosts(PostsCollection $posts);
}
// instead of
interface FeedGenerator
{
public function generateFromPosts(array $posts);
}