The goal here is to pull an item from an array and when the array ends - to start over - and allow you to pull items infinitely as needed. We don't use PHP that much, so please let us know how we can write this succinctly and with best practices. :)

class ColorGenerator {

    public function __construct($colors) {
        //   "property"
        $this->colors = $colors;
        $this->listLength = count($colors);
        $this->index = 0;

        // $this references the object that this class will create

    //              "method"
    public function nextColor() {
        $color = $this->colors[$this->index];
        if ($this->index >= $this->listLength - 1) {
            $this->index = 0;
        } else {
        return $color;

// "object"    using "class"    ['red', 'blue', 'green', 'etc']
$rainbow = new ColorGenerator($database['colors']);

And looking at this now, it could just be generic since it's pulling any item out of any simple array. It feels like there could be a built-in function/construct for this that we don't know about.


function namesRainbow($names, $colors) {
    $rainbow = new ColorGenerator($colors);

    foreach ($names as $name) {
        $nextColor = $rainbow->nextColor();

// in some page section
namesRainbow($database["names"], $database["colors"]);
  • \$\begingroup\$ how/when are the colors generated being used? \$\endgroup\$
    – depperm
    Commented Jan 5, 2023 at 13:42
  • \$\begingroup\$ In this case, a student is using the colors in a loop that generates a person-card and she wants each card to have a different background color - based on an outside list of colors (separate from the person data) \$\endgroup\$ Commented Jan 5, 2023 at 13:56
  • 2
    \$\begingroup\$ Note that general questions about "best practices" are specifically off-topic here. We just review the specific code that's posted. \$\endgroup\$ Commented Jan 5, 2023 at 15:31
  • \$\begingroup\$ Yeah. I get it. But - 'best practices' are going to be what you suggest - because you're the best - right? ;) \$\endgroup\$ Commented Jan 6, 2023 at 0:38
  • \$\begingroup\$ Let's just call them - effective methods \$\endgroup\$ Commented Jan 6, 2023 at 0:38

1 Answer 1


You may use the InfiniteIterator

The InfiniteIterator accepts another iterator, to make it work with array, you need to wrap array in in an ArrayIterator. We can add named constructor to simplify construction from array.

Declare class properties. Dynamically creating properties is deprecated since PHP 8.2.

I also recommend to add parameter and return types wherever possible. The code then better communicates the intent.

You should throw error if the set of colors is empty, because the generator would then have nothing to generate.

Since PHP 8.1 we can make properties readonly to prevent accidental overwrites. And since PHP 8.2 we can make the entire class readonly which is equivalent to making all of its properties readonly.

As a best practice, I also recommend to make the class final, unless you actually intend to extend the class which seems unlikely.

final class ColorGenerator
// or final readonly class ColorGenerator
    private readonly \InfiniteIterator $colors;

     * @param \Iterator<string> $colors
    public function __construct(\Iterator $colors)
        $this->colors = new \InfiniteIterator($colors);
        if (!$this->colors->valid()) {
            throw new \InvalidArgumentException('Input iterator cannot be empty');

    public static function fromArray(array $colors): self
        return new self(new \ArrayIterator($colors));

    public function nextColor(): string
        $color = $this->colors->current();
        return $color;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.