Sunday, January 30, 2011

The Indium Includer and Class Loader

Indium comes with its own includer class called Core\Includer. This class contains a thin set of wrappers around PHP:s native include language construct. In an Indium application, every file system operation that depends on the include_path ini setting should be routed through Core\Includer. Of course, an application may choose to use include or file_get_contents directly, but this is neither supported nor encouraged.

Why does Indium encourage applications to wrap includes?
  1. First and foremost, we want to fight a potentially dangerous "feature" of PHP:s includer. If the specified file cannot be found in include_path, PHP will silently search the current directory and the directory in which the calling script resides. This behavior has unpredictable (run time dependent) security implications, encourages the generation of implicit dependencies and imposes an unnecessary cost in terms of file system operations. The only way to turn this "feature" off is to specify an absolute path, or a path which is relative to the current directory. Core\Includer scans include_path to determin the absolute path of includes before calling on PHP:s native includer.
  2. Controlling the scope inside which the include takes place. For reasons of encapsulation and security, Indium has to be able to decide what is visible to an included view.
  3. PHP:s includer is a swiss army knife. Wrapping and controlling it helps us in identifying common include idioms and providing standard, Indium blessed methods for carrying them out.
  4. We love classes. We want to encourage application writers to use classes. Applications should rely on Indium's Core\ClassLoader for autoloading.
  5. Lastly, wrapping includes enables us to impose strict validation on file names, which helps with tightening up security.


Okay, that's the Indium includer covered, on to the class loader. The Indium class loader provides a unified and highly configurable interface to class loading. It hooks into PHP SPL:s autoloading infrastructure and sits on top of Core\Includer. Essentially, the class loader provides a mapping from ( namespace path, class name ) tuples to include paths. Include paths may be searched to any specified depth. In addition the class loader has "magic" hooks for Indium exceptions and interfaces; these are automatically searched for in subdirs named "exceptions" and "interfaces". The best thing about Indium's class loader and includer is that the appplication need not really care about them. As long as your put your controllers and models in APPLICATION_PATH/controllers and APPLICATION_PATH/models, things are guaranteed to just work.

Core\Includer and Core\ClassLoader has proven to be a very strong and robust combination which gives a reliable and secure foundation to the Indium framework.

2 comments:

Unknown said...

This is exactly how NanoMVC works FYI. It has an autoloaded injective mapping between class names and their locations. It must have been years since I used the include() or require() function..

Unknown said...

Yea... of course you loose some flexibility without include() but you gain in more security and controll and that's they way to go!

More info at http://www.indium-framework.com