You could try making your own collection type, which validates that everything is a vehicle, but also enforces they're all the same type of vehicle.
<?php class Vehicle {} class Car extends Vehicle {} class SUV extends Vehicle {} // This doesn't need to be an SplDoublyLinkedList, it's just // a convenient datastructure to demo with class VehicleCollection extends SplDoublyLinkedList { public function add($index, Vehicle $obj) { $this->validateType($obj); parent::add($index, $obj); } public function push(Vehicle $obj) { $this->validateType($obj); parent::push($obj); } protected function validateType($obj) { // If we have anything in here, ensure next is the same vehicle type if (!($this->isEmpty() || $this->top() instanceof $obj)) { throw new InvalidArgumentException('Argument passed to ' . __CLASS__ . '::' . __FUNCTION__ . ' must all be instances of same type.'); } } } // Make a new collection $col = new VehicleCollection(); // Let's have a couple cars $car = new Car; $car2 = new Car; // And an SUV $suv = new SUV; // Let's add our cars $col->push($car); $col->push($car2); var_dump($col); /* Collection right now: class VehicleCollection#1 (2) { private $flags => int(0) private $dllist => array(2) { [0] => class Car#2 (0) { } [1] => class Car#3 (0) { } } } */ // Now we try to add an SUV $col->push($suv); // and get this: // PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Argument passed to VehicleCollection::validateType must all be instances of same type.'
This has the added benefit that if you further extended, e.g. made a class SportsCar extends Car {}, that SportsCar could go into your collection.
It was pointed out that I might have been misinterpreting your question. If you're just trying to filter an array, this becomes a much simpler problem. I wouldn't bother to even implement a special class if that's the case - just pass a Closure into array_filter, which is quite readable and an easy pattern to follow elsewhere:
$vehicles = [$car, $suv, $car2]; $cars = array_filter($vehicles, function($vehicle) { return $vehicle instanceof Car; }); $suvs = array_filter($vehicles, function($vehicle) { return $vehicle instanceof SUV; });
So in that example, the array of vehicles has an SUV, and once filtered, the $cars array has only the cars. If you want to make that a class method, you could do something along the lines of:
public function getAllOfType($type) { return array_filter( $this->vehicles, function($vehicle) { return is_a($vehicle, $type); } ); }
Then to grab only cars from your collection:
$cars = $myVehicleCollection->getAllOfType('Car');
Vehicle.