Upon comparison, Repositories are different than a collection if we consider their querying ability. A Repository deals with a large set of objects that typically aren't in memory when the query is performed. It's not feasible to load all the instances of a Domain object in memory and perform a query over them.
A good solution is to pass a criterion and let the Repository handle the implementation details to successfully perform the operation. It might translate the criterion to SQL or ORM queries or iterate over an in-memory collection. However, it doesn't matter, because the implementation deals with it.
A common implementation for the criterion object is the Specification pattern. A specification is a simple predicate that takes a Domain object and returns a boolean. Given a Domain object, it will return true if it specifies the specification, and false otherwise:
interface PostSpecification { /** * @return boolean */ public function...