<?php
namespace SepomexPhp;

class Locations implements \IteratorAggregate, \Countable
{
    /** @var Location[] */
    private $collection;

    public function __construct(Location ...$location)
    {
        $this->collection = $location;

    public static function extractUniqueCities(Location ...$locations): Cities
    {
        // This method is static because it does not use $this
        $cities = [];
        foreach ($locations as $location) {
            if ($location->hasCity()) {
                $city = $location->city();
                if (! array_key_exists($city->id(), $cities)) {
                    $cities[$city->id()] = $location->city();
                }
            }
        }
        return new Cities(...$cities);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->collection);
    }

    public function count(): int
    {
        return count($this->collection);
    }

    /**
     * @return Cities|City[]
     */
    public function cities(): Cities
    {
        $cities = [];
        foreach ($this->collection as $location) {
            if ($location->hasCity()) {
                $city = $location->city();
                if (! array_key_exists($city->id(), $cities)) {
                    $cities[$city->id()] = $location->city();
                }
            }
        }
        return new Cities(...$cities);
    }

    public function asArray(): array
    {
        $array = [];
        foreach ($this->collection as $location) {
            $array[] = $location->asArray();
        }
        return $array;
    }
}

<?php
namespace SepomexPhp;

class Locations implements \IteratorAggregate, \Countable
{
    /** @var Location[] */
    private $collection;

    /** @var Cities */
    private $cities;

    public function __construct(Location ...$location)
    {
        $this->collection = $location;
        $this->cities = $this->extractUniqueCities(...$location);
    }

    public static function extractUniqueCities(Location ...$locations): Cities
    {
        // This method is static because it does not use $this
        $cities = [];
        foreach ($locations as $location) {
            if ($location->hasCity()) {
                $city = $location->city();
                if (! array_key_exists($city->id(), $cities)) {
                    $cities[$city->id()] = $location->city();
                }
            }
        }
        return new Cities(...$cities);
    }

    public function getIterator()
    {
        return new \ArrayIterator($this->collection);
    }

    public function count(): int
    {
        return count($this->collection);
    }

    /**
     * @return Cities|City[]
     */
    public function cities(): Cities
    {
        return $this->cities;
    }

    public function asArray(): array
    {
        $array = [];
        foreach ($this->collection as $location) {
            $array[] = $location->asArray();
        }
        return $array;
    }
}

Make cities a property, set inside constructor
Make cities a property, set inside constructor

