user838531
user838531

Reputation: 488

Is this PHP recursion nonsense?

This code represents some sort of recursion.

class Login implements Subject
{
    protected $observers = [];
    public function attach($observable)
    {
        if (is_array($observable)) {
            foreach ($observable as $observer) {
                $this->attach($observer);
            }
            return;
        }
        $this->observers[] = $observable;
        return $this;
    }
}

$login->attach([
    new LogHandler,
    new EmailNotifier
]);

I have three questions about this code:

  1. is_array($observable) is executed for every single entry in the array $observable, right? Let's say the array $observable would have 100 entries. Would is_array() be executed 100 times, for every single array item?

  2. How does foreach work here? It seems to jump out of the foreach loop and execute attach() and then return back to the loop until the end of the array is reached?

  3. How does return; work here?

Either I don't get it, or this is a strange piece of code which makes no sense and includes unnecessary steps.

Upvotes: 2

Views: 95

Answers (1)

elixenide
elixenide

Reputation: 44841

It's not nonsense. It just provides a way to pass either a single, non-array value or an array of values. The is_array() check and recursive calls to attach() are how it decides whether (1) to add $observable itself when $observable is not an array or (2) to add each element of $observable when $observable is an array.

To answer your specific questions:

  1. Yes, if $observable is an array, then is_array() gets called once for $observable on the first call, then one more time for each element in the array. It may get called even more times if $observable contains nested arrays, like [$obj1, [$obj2, $obj3]].

  2. The foreach just loops over the array (that is, if $observable is an array). It attaches each element of $observable, then returns. It should probably return $this whether or not $observable is an array, both for consistency and to allow method chaining, like $login->attach(new LogHandler)->attach(new EmailNotifier)->attach(new Foo);. That said, there's nothing inherently wrong with it.

  3. return; just exits the function. Again, it should probably be return $this; for consistency and to allow method chaining, but it's not doing anything special.

Upvotes: 3

Related Questions