back

Bendegúz Csirmaz

This post is part of a series based on a presentation I gave at Cheppers on March 20, 2019.

PHP quiz #4 - hoisting

Developing modern object oriented applications kept me in blissful ignorance of PHP's less used features. The following may come as a surprise to unsuspecting programmers (such as myself).

Question

What will this code output?

<?php

echo helloWorld();

function helloWorld() {
  return "Hello World!\n";
}
  • A Fatal error: Uncaught Error: Call to undefined function helloWorld()
  • B Nothing
  • C Hello World!
  • D Warning + "helloWorld()"

Answer

Show the answer
C
Hello World!

Explanation

Hoisting

Similarly to JavaScript, function declarations are resolved at compile time. By the time the interpreter calls our function, it will have been already defined. The program will run without any problems.

Restrictions on hoisting

When the function is defined conditionally, this is not the case. For hoisting to work, it has to be defined on the top level. The following will throw a fatal error:

<?php

if (true) {
  // Fatal error: Uncaught Error: Call to undefined function helloWorld().
  echo helloWorld();

  function helloWorld() {
    return "Hello World!\n";
  }
}

Includes

What about includes?

Naturally, they are only resolved at runtime. When including a function, the include statement must run before the function call.

<?php

// Fatal error: Uncaught Error: Call to undefined function helloWorld().
echo helloWorld();

// Includes the helloWorld function.
include "helloWorld.php";

Classes

Functions are not the only unit of code organization (thank god).

Hoisting applies to class, interface and trait declarations too. More or less.

<?php

class A extends B {}
class B {}

// OK!

It becomes less graceful when multiple levels of inheritance is introduced.

<?php

class A extends B {}
class B extends C {}
class C {}

// Fatal error: Class 'B' not found in ...

Conclusion

Avoiding top level functions and declaring one class per file is considered as best practice.

This eliminates the possibility of ever relying on PHP to hoist your code.

There is no good reason to use hoisting anyways. Not even if a situation (caused by poor design decisions) allows it.

The next post will be different. We'll stop focusing on things you shouldn't do. Instead, we'll learn about an important concept used in real world applications.

<< previous

next >>