Where PHP finds the file(s) of a namespace

Context: When I introduced the Monolog logging library to https://mü and me wondering how the use keyword works.

Especially I didn't understand how PHP knows where to find the file(s) the Monolog namespace is defined in. So when (one of) Monolog's namespace is Monolog\Logger, does PHP require that there is a file at a path such as ./Monolog/Logger.php. The short answer is no!

PHP does not specify where the file a namespace is defined in should be located. At the end of the day, it still boils down to using the good old require and include statements. That means you could have a file at ./foo.php defining the rather nested namespace a\quick\brown\fox. And all you have to do to use this namespace in some other script is to require foo.php and import the namespace with use a\quick\brown\fox. That's it. You still have to "require" (or "include") files. And the annoying thing is that PHP's doc on namespaces doesn't mention this at all.

So isn't that cumbersome? Yes it is.

autoloading to the rescue? Not quite.

However, there's one partial solution called autoloading. But why only partial? Because autoloading only works for "class-like constructs" such as classes, traits, interfaces and enumerations. See

In my app I am only using functions so far. So autoloading won't help me much.

However, I still need to import Monolog. How does that work now?

Well, since I'm using composer to manage external dependencies, I'll also use composer's ready-made autoloading function. Because composer provides an autoloading function implementation that "knows" the structure of composers vendor directory and as a result knows where to find the files that define the imported namespaces.

But hold on, there's one more important thing for this to work: composer adheres to the autoloader convention defined in PSR-4. And this convention defines the piece missing in PHP: where files should be located with respect to the namespaces they define. And the convention roughly is that namespace and filesystem paths should match.

Published by Robert Möstl

« Back to Blog