Take the 2-minute tour ×


I am programming in a native Linux file system.

I have a class of HelpTopic:

class HelpTopic extends Help{}

And a class of Help:

class Help{}

Now I go to include HelpTopic:




My best guess is that there is some oddity with Linux that causes PHP to react this way but not sure what.

Does anyone have any ideas or solutions to this problem?


I have added my loading function to show what I am doing:

public static function import($cName, $cPath = null){

    if(substr($cName, -2) == "/*"){

        $d_name = ROOT.'/'.substr($cName, 0, -2);
        $d_files = getDirectoryFileList($d_name, array("\.php")); // Currently only accepts .php

        foreach($d_files as $file){
            glue::import(substr($file, 0, strrpos($file, '.')), substr($cName, 0, -2).'/'.$file);
        if(!$cPath) $cPath = self::$_classMapper[$cName];

            self::$_classLoaded[$cName] = true;
            if($cPath[0] == "/" || preg_match("/^application/i", $cPath) > 0 || preg_match("/^glue/i", $cPath) > 0){
                return include ROOT.'/'.$cPath;
                return include $cPath;
        return true;

I call this by doing glue::inmport('application/models/*'); and it goes through including all the models in my app. Thing is PHP on a linux based file system (not on cifs) is trying to load the parents of my classes without instantiation.

This is a pretty base function that exists in most frameworks (in fact most of this code is based off of yiis version) so I am confused why others have not run into this problem.

share|improve this question
You need to inclue file with Help class. Or i miss something? –  CSharpRU Jan 18 '12 at 14:53
On cifs I can include the file Help after the HelpTopic which makes it easier to load an entire directory, but on Native Linux file system I must have parent included before child for some reason. –  Sammaye Jan 18 '12 at 14:55
add comment

1 Answer

up vote 4 down vote accepted

And even though I do not instantiate HelpTopic with new HelpTopic() PHP still reads the class signature and tries to load Help with HelpTopic.


In order to know how to properly define a class, PHP needs to resolve any parent classes (all the way up) and any interfaces. This is done when the class is defined, not when the class is used.

You should probably review the PHP documentation on inheritance, which includes a note explaining this behavior:

Unless autoloading is used, then classes must be defined before they are used. If a class extends another, then the parent class must be declared before the child class structure. This rule applies to class that inherit other classes and interfaces.

There are two ways to resolve this problem.

First, add a require_once at the top of the file that defines the child class that includes the file defining the parent class. This is the most simple and straight-forward way, unless you have an autoloader.

The second way is to defione an autoloader. This is also covered in the documentation.

The ... thing ... you're using there is not an autoloader. In fact, it's a horrible abomination that you should purge from your codebase. It's a performance sap and you should not be using it. It also happens to be the thing at fault.

We don't have the definition of getDirectoryFileList() here, so I'll assume it uses either glob() or a DirectoryIterator. This is the source of your problem. You're getting the file list in an undefined order. Or, rather, in whatever order the underlying filesystem wants to give to you. On one machine, the filesystem is probably giving you Help.php before HelpTopic.php, while on the other machine, HelpTopic.php is seen first.

At first glance, you might think this is fixable with a simple sort, but it's not. What happens if you create a Zebra class, and then later need to create an AlbinoZebra that inherits from it? No amount of directory sorting is going to satisfy both the "load ASCIIbetical" and the "I need the Zebra to be first" requirements.

Let's also touch on the performance aspect of the problem. On every single request, you're opening a directory and reading the list of files. That's one hell of a lot of stat calls. This is slow. Very slow. Then, one by one, regardless of whether or not you'll need them, you're including the files. This means that PHP has to compile and interpret every single one of them. If you aren't using a bytecode cache, this is going to utterly destroy performance if the number of files there ever grows to a non-trivial number.

A properly constructed autoloader will entirely mitigate this problem. Autoloaders run on demand, meaning that they'll never attempt to include a file before it's actually needed. Good-performing autoloaders will know where the class file lives based on the name alone. In modern PHP, it's accepted practice to name your classes such that they'll be found easily by an autoloader, using either namespaces or underscores -- or both -- to map directory separators. (Meaning namespace \Models; class Help or class Models_Help would live in Models/Help.php)

Unfortunately most examples won't be useful here, as I don't know what kind of weird things your custom framework does. Take a peek at the Zend Framework autoloader, which uses prefix registration to point class prefixes (Model_) at directories.

share|improve this answer
But then how come my code works on a cifs share file system if PHP is always meant to act this way? –  Sammaye Jan 18 '12 at 17:46
Oops, in between the time I started writing this and finally hit the submit button, you added some new code to your question. Let me review things. –  Charles Jan 18 '12 at 17:48
Your answer did it! I found out the reason. In Linux "Help" is the last class to be found in the directory by PHP while in Cifs it is actually the first which means it loads it first! I just assumed the directory will always come into PHP in ascendening order. Thanks! You really helped me :D. –  Sammaye Jan 18 '12 at 17:57
Indeed, but it gets worse. I've updated my answer. –  Charles Jan 18 '12 at 18:11
Ah I see, With that I think I can come up with something 100x better now. This is my first time coding a MVC from scratch so having this info is like gold dust to me. Thing is in Yii you can tell it to load (and they say should) your Models directory entirely (this is where I havbe taken a lot of my inspiration), but seems now I shouldnt go down the same path right? Cos either way they will have to lots of stat() calls. I'll rewrite my function to run on the principles you've shown thanks :) –  Sammaye Jan 18 '12 at 18:19
show 4 more comments

Your Answer


