Request for Comments: Loop+Else control structure


Performing a set of actions upon *not* entering a loop is a very common programming necessity. This RFC proposes an optional “else” clause that can be used after while, for, and foreach loops to simplify handling of this particular scenario.

A secondary objective of this RFC is to bring closure to a number of requests in bug tracker (hopefully they can be closed after this, whatever the resolution).


Proposed syntax will look as follows:

And for comparison purposes, the following block (it's obviously longer and less elegant) contains the same code written without loop+else:

How does this work?

When is loop's "else" clause executed?

Proposed “else” clause will be executed only if main loop body has *not* been entered at least once (i.e. loop condition was never satisfied). For this reason do-while loop cannot have this syntax (as it is guaranteed that its body will be entered at least once).

So in general, a loop+else construct is the equivalent of the following user code:

What about loops without a body?

I suggest loops without a body should not be allowed to have an alternate “else” clause:

What is the precedence?

In order to avoid BC breaks when single-statement blocks are not enclosed in {}'s, any ambiguity should always be resolved in favor of if's. This means that in the following sample “else” block belongs to the “if”, and not the “while”:

However, when there is no conflict between a loop and an “if”, this should be resolved in favor of the “closest” loop, just like it is now with if's. This means that in the following sample “else” belongs to the “foreach” loop, and not the “while”:

Alternative syntax for control structures

This should work as expected (while respecting the precedence order described above), e.g.:

How about elseif?

Under this proposal, the following PHP code would be valid:

Because of that, I believe it would make sense to allow loop+elseif syntax as well.


  • This makes code shorter, more flat, and more readable. (this is the primary objective)
    • Eliminates the annoyance of having to use flag variables in a lot of common use-cases
    • Code is more structured and predictable (e.g. no more if's that can come before OR after the loop)
  • No new keywords
  • No BC breaks
  • PHP would not be the first language to implement such a structure. Python has it (although it behaves differently there).
  • This feature has almost universal support in userland (related feature requests in bug tracker are among the highest rated of all time)


  • “This new syntax is excessive and can be confusing to new developers” ©
  • “This violates the KISS principle” ©
  • Overhead?
  • Complicated changes to the parser? Too much work for a relatively minor syntax sugar?
  • This syntax is not supported by any of the “big mountains” like C, C++, Java, or C#. (the former being most notable since PHP is written in it)

Common Misconceptions

  • Proposed syntax can be achieved by a simple “if” statement before or after the loop.
    • While true in some cases (for example in most “foreach” cases this is indeed true), in others (e.g. when checked data is modified inside the loop) a temporary variable will be required to keep track of whether the loop has been entered. This is illustrated in “while” example in the Syntax section.
    • Even when temporary variable can be avoided, an extra “if” statement will require the repetition of loop's condition inside the “if”, which can contain a very expensive and/or long calculation (see “for” example is Syntax section).

Alternative Proposals

We could also do it the Python way, which means executing “else” upon the natural completion of the loop, and only skipping it on break, continue, or throw. I personally see this a lot less useful than this proposal.


Original discussions in bug tracker:

while {} else {} (by php at bellytime dot com)

Build in foreach else support (by kjarli at gmail dot com)

For... else construct (by jeroenvandenenden at gmail dot com)


May 10, 2012 - RFC draft created

rfc/loop_else.txt · Last modified: 2012/05/11 05:07 by ravazin