<p>I'm wondering what the best practice is for handling the problem with having to "include" so many files in my PHP scripts in order to ensure that all the classes I need to use are accessible to my script. </p>

<p>Currently, I'm just using <a href="http://php.net/manual/en/function.include-once.php" rel="nofollow noreferrer">include_once</a> to include the classes I access directly.  Each of those would <code>include_once</code> the classes that they access. </p>

<p>I've looked into using the <code>__autoload</code> function, but hat doesn't seem to work well if you plan to have your  class files organized in a directory tree.  If you did this, it seems like you'd end up walking the directory tree until you found the class you were looking for.  <strong><em>Also, I'm not sure how this effects classes with the same name in different namespaces.</em></strong>  </p>

<p><strong>Is there an easier way to handle this?</strong>  </p>

<p>Or is PHP just not suited to "<strong>enterprisey</strong>" type applications with lots of different objects all located in separate files that can be in many different directories.</p>

[{'answer_id': 23805, 'author': 'Konrad Rudolph', 'author_id': 1968, 'author_profile': 'https://Stackoverflow.com/users/1968', 'pm_score': 0, 'selected': False, 'text': "<p><code>__autoload</code> works well if you have a consistent naming convention for your classes that tell the function where they're found inside the directory tree. MVC lends itself particularly well for this kind of thing because you can easily split the classes into models, views and controllers.</p>\n\n<p>Alternatively, keep an associative array of names to file locations for your class and let <code>__autoload</code> query this array.</p>\n"}, {'answer_id': 23806, 'author': 'JasonMichael', 'author_id': 1935, 'author_profile': 'https://Stackoverflow.com/users/1935', 'pm_score': 0, 'selected': False, 'text': '<p><code>__autoload</code> will work, but only in PHP 5.</p>\n'}, {'answer_id': 23829, 'author': 'Kevin', 'author_id': 40, 'author_profile': 'https://Stackoverflow.com/users/40', 'pm_score': 2, 'selected': False, 'text': '<p>You can define multiple autoloading functions with spl_autoload_register:</p>\n\n<pre><code>spl_autoload_register(\'load_controllers\');\nspl_autoload_register(\'load_models\');\n\nfunction load_models($class){\n    if( !file_exists("models/$class.php") )\n        return false;\n\n    include "models/$class.php";\n    return true;\n}\nfunction load_controllers($class){\n    if( !file_exists("controllers/$class.php") )\n        return false;\n\n    include "controllers/$class.php";\n    return true;\n}\n</code></pre>\n'}, {'answer_id': 23872, 'author': 'Brock Boland', 'author_id': 2185, 'author_profile': 'https://Stackoverflow.com/users/2185', 'pm_score': 0, 'selected': False, 'text': "<p>Of the suggestions so far, I'm partial to Kevin's, but it doesn't need to be absolute.  I see a couple different options to use with __autoload.</p>\n\n<ol>\n<li>Put all class files into a single directory.  Name the file after the class, ie, <code>classes/User.php</code> or <code>classes/User.class.php</code>.</li>\n<li>Kevin's idea of putting models into one directory, controllers into another, etc.  Works well if all of your classes fit nicely into the MVC framework, but sometimes, things get messy.</li>\n<li>Include the directory in the classname.  For example, a class called Model&#95;User would actually be located at <code>classes/Model/User.php</code>.  Your __autoload function would know to translate an underscore into a directory separator to find the file.</li>\n<li>Just parse the whole directory structure once.  Either in the __autoload function, or even just in the same PHP file where it's defined, loop over the contents of the <code>classes</code> directory and cache what files are where.  So, if you try to load the <code>User</code> class, it doesn't matter if it's in <code>classes/User.php</code> or <code>classes/Models/User.php</code> or <code>classes/Utility/User.php</code>.  Once it finds <code>User.php</code> somewhere in the <code>classes</code> directory, it will know what file to include when the <code>User</code> class needs to be autoloaded.</li>\n</ol>\n"}, {'answer_id': 24074, 'author': 'Konrad Rudolph', 'author_id': 1968, 'author_profile': 'https://Stackoverflow.com/users/1968', 'pm_score': 0, 'selected': False, 'text': '<p>@Kevin:</p>\n\n<blockquote>\n  <p>I was just trying to point out that spl_autoload_register is a better alternative to __autoload since you can define multiple loaders, and they won\'t conflict with each other. Handy if you have to include libraries that define an __autoload function as well.</p>\n</blockquote>\n\n<p>Are you sure? The <a href="http://www.php.net/function.spl_autoload_register" rel="nofollow noreferrer">documentation</a> says differently:</p>\n\n<blockquote>\n  <p>If your code has an existing __autoload function then this function must be explicitly registered on the __autoload stack. This is because spl_autoload_register() will effectively replace the engine cache for the __autoload function by either spl_autoload() or spl_autoload_call().</p>\n</blockquote>\n\n<p>=> you have to explicitly register any library\'s <code>__autoload</code> as well. But apart from that you\'re of course right, this function is the better alternative.</p>\n'}, {'answer_id': 24106, 'author': 'Michał Niedźwiedzki', 'author_id': 2169, 'author_profile': 'https://Stackoverflow.com/users/2169', 'pm_score': 4, 'selected': True, 'text': '<p>I my applications I usually have <code>setup.php</code> file that includes all core classes (i.e. framework and accompanying libraries). My custom classes are loaded using autoloader aided by directory layout map.</p>\n\n<p>Each time new class is added I run command line builder script that scans whole directory tree in search for model classes then builds associative array with class names as keys and paths as values. Then, __autoload function looks up class name in that array and gets include path. Here\'s the code:</p>\n\n<p><strong>autobuild.php</strong></p>\n\n<pre><code>define(\'MAP\', \'var/cache/autoload.map\');\nerror_reporting(E_ALL);\nrequire \'setup.php\';\nprint(buildAutoloaderMap() . " classes mapped\\n");\n\nfunction buildAutoloaderMap() {\n    $dirs = array(\'lib\', \'view\', \'model\');\n    $cache = array();\n    $n = 0;\n    foreach ($dirs as $dir) {\n        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $entry) {\n            $fn = $entry-&gt;getFilename();\n            if (!preg_match(\'/\\.class\\.php$/\', $fn))\n                continue;\n            $c = str_replace(\'.class.php\', \'\', $fn);\n            if (!class_exists($c)) {\n                $cache[$c] = ($pn = $entry-&gt;getPathname());\n                ++$n;\n            }\n        }\n    }\n    ksort($cache);\n    file_put_contents(MAP, serialize($cache));\n    return $n;\n}\n</code></pre>\n\n<p><strong>autoload.php</strong></p>\n\n<pre><code>define(\'MAP\', \'var/cache/autoload.map\');\n\nfunction __autoload($className) {\n    static $map;\n    $map or ($map = unserialize(file_get_contents(MAP)));\n    $fn = array_key_exists($className, $map) ? $map[$className] : null;\n    if ($fn and file_exists($fn)) {\n        include $fn;\n        unset($map[$className]);\n    }\n}\n</code></pre>\n\n<p>Note that file naming convention must be [class_name].class.php. Alter the directories classes will be looked in <code>autobuild.php</code>. You can also run autobuilder from autoload function when class not found, but that may get your program into infinite loop.</p>\n\n<p>Serialized arrays are darn fast.</p>\n\n<p>@JasonMichael: PHP 4 is dead. Get over it.</p>\n'}, {'answer_id': 24137, 'author': 'Polsonby', 'author_id': 137, 'author_profile': 'https://Stackoverflow.com/users/137', 'pm_score': 1, 'selected': False, 'text': '<p>You can also programmatically determine the location of the class file by using structured naming conventions that map to physical directories. This is how Zend do it in <a href="http://framework.zend.com/" rel="nofollow noreferrer">Zend Framework</a>. So when you call <code>Zend_Loader::loadClass("Zend_Db_Table");</code> it explodes the classname into an array of directories by splitting on the underscores, and then the Zend_Loader class goes to load the required file.</p>\n\n<p>Like all the Zend modules, I would expect you can use just the loader on its own with your own classes but I have only used it as part of a site using Zend\'s MVC.</p>\n\n<p>But there have been concerns about performance under load when you use any sort of dynamic class loading, for example see <a href="http://blog.digitalstruct.com/2007/12/23/zend-framework-performance-zend_loader/" rel="nofollow noreferrer">this blog post</a> comparing Zend_Loader with hard loading of class files. </p>\n\n<p>As well as the performance penalty of having to search the PHP include path, it defeats opcode caching. From a comment on that post:</p>\n\n<blockquote>\n  <blockquote>\n    <p>When using ANY Dynamic class loader APC can’t cache those files fully as its not sure which files will load on any single request. By hard loading the files APC can cache them in full.</p>\n  </blockquote>\n</blockquote>\n'}]
['https://Stackoverflow.com/questions/23802', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1862/']