Autoload classes from different folders

前端 未结 12 933
不知归路
不知归路 2020-11-28 19:35

This is how I autoload all the classes in my controllers folder,

# auto load controller classes
    function __autoload($class_name) 
    {
             


        
相关标签:
12条回答
  • 2020-11-28 19:58

    Here is my solution,

    /**
         * autoload classes 
         *
         *@var $directory_name
         *
         *@param string $directory_name
         *
         *@func __construct
         *@func autoload
         *
         *@return string
        */
        class autoloader
        {
            private $directory_name;
    
            public function __construct($directory_name)
            {
                $this->directory_name = $directory_name;
            }
    
            public function autoload($class_name) 
            { 
                $file_name = 'class_'.strtolower($class_name).'.php';
    
                $file = AP_SITE.$this->directory_name.'/'.$file_name;
    
                if (file_exists($file) == false)
                {
                    return false;
                }
                include ($file);
            }
        }
    
        # nullify any existing autoloads
        spl_autoload_register(null, false);
    
        # instantiate the autoloader object
        $classes_1 = new autoloader('controllers');
        $classes_2 = new autoloader('models');
    
        # register the loader functions
        spl_autoload_register(array($classes_1, 'autoload'));
        spl_autoload_register(array($classes_2, 'autoload'));
    

    I'm not sure whether it is the best solution or not but it seems to work perfectly...

    What do you think??

    0 讨论(0)
  • 2020-11-28 19:59

    __autoload() function should not be use because it is not encourged. Use spl_autoload(), spl_autoload_register() instead. __autoload() just can load one class but spl_autoload() can get more than 1 classes. And one thing more, in future __autoload() may deprecated. More stuff can be find on http://www.php.net/manual/en/function.spl-autoload.php

    0 讨论(0)
  • 2020-11-28 20:05

    I use this. Basically define your folder structure (MVC etc) as a constant in a serialised array. Then call the array in your autoload class. Works efficiently for me.

    You could obviously create the folder array using another function but for MVC you may as well type it in manually.

    For this to work you need to call your classes ...... class.classname.php

      //in your config file
        //define class path and class child folders
        define("classPath","classes");
        define("class_folder_array", serialize (array ("controller", "model", "view")));
    
    
      //wherever you have your autoload class
        //autoload classes
        function __autoload($class_name) {
        $class_folder_array = unserialize (class_folder_array);
        foreach ($class_folder_array AS $folder){
            if(file_exists(classPath."/".$folder.'/class.'.$class_name.'.php')){require_once classPath."/".$folder.'/class.'.$class_name.'.php';break;}
        }
    
    
    
        }
    
    0 讨论(0)
  • 2020-11-28 20:06

    Here's what I'd do:

    function __autoload($class_name) {
        $class_name = strtolower($class_name);
        $filename = 'class_'.$class_name.'.php';
    
        if (substr($class_name, 0, 5) === 'model') {
            $file = AP_SITE.'models/'.$filename;
        } else $file = AP_SITE.'controllers/'.$filename;
    
        if (!is_file($file)) return false;
        include $file;
    }
    

    As long you name your files consistently, like class_controller_*.php and class_model_*.php, this should work fine.

    0 讨论(0)
  • 2020-11-28 20:07

    I see you are using controller_***** and model_***** as a class naming convention.

    I read a fantastic article, which suggests an alternative naming convention using php's namespace.

    I love this solution because it doesn't matter where I put my classes. The __autoload will find it no matter where it is in my file structure. It also allows me to call my classes whatever I want. I don't need a class naming convention for my code to work.

    You can, for example, set up your folder structure like:

    • application/
      1. controllers/
        • Base.php
        • Factory.php
      2. models/
        • Page.php
        • Parent.php

    Your classes can be set up like this:

    <?php
    namespace application\controllers;
    class Base {...}
    

    and:

    <?php
    namespace application\models;
    class Page {...}
    

    The autoloader could look like this (or see 'a note on autoloading' at the end):

    function __autoload($className) {
        $file = $className . '.php';
        if(file_exists($file)) {
            require_once $file;
        }
    }
    

    Then... you can call classes in three ways:

    $controller = new application\controllers\Base();
    $model = new application\models\Page();
    

    or,

    <?php
    use application\controllers as Controller;
    use application\models as Model;
    
    ...
    
    $controller = new Controller\Base();
    $model = new Model\Page();
    

    or,

    <?php
    use application\controllers\Base;
    use application\models\Page;
    
    ...
    
    $controller = new Base();
    $model = new Page();
    

    EDIT - a note on autoloading:

    My main auto loader looks like this:

    // autoload classes based on a 1:1 mapping from namespace to directory structure.
    spl_autoload_register(function ($className) {
    
        # Usually I would just concatenate directly to $file variable below
        # this is just for easy viewing on Stack Overflow)
            $ds = DIRECTORY_SEPARATOR;
            $dir = __DIR__;
    
        // replace namespace separator with directory separator (prolly not required)
            $className = str_replace('\\', $ds, $className);
    
        // get full name of file containing the required class
            $file = "{$dir}{$ds}{$className}.php";
    
        // get file if it is readable
            if (is_readable($file)) require_once $file;
    });
    

    This autoloader is a direct 1:1 mapping of class name to directory structure; the namespace is the directory path and the class name is the file name. So the class application\controllers\Base() defined above would load the file www/application/controllers/Base.php.

    I put the autoloader into a file, bootstrap.php, which is in my root directory. This can either be included directly, or php.ini can be modified to auto_prepend_file so that it is included automatically on every request.

    By using spl_autoload_register you can register multiple autoload functions to load the class files any which way you want. Ie, you could put some or all of your classes in one directory, or you could put some or all of your namespaced classes in the one file. Very flexible :)

    0 讨论(0)
  • 2020-11-28 20:07

    I have to mention something about "good" autoload scripts and code structure, so read the following CAREFULLY


    Keep in Mind:

    • Classname === Filename
    • Only ONE class per file

    e.g: Example.php contains

    class Example {}
    
    • Namespace === Directory structure

    e.g: /Path1/Path2/Example.php matches

    namespace Path1\Path2;
    class Example {}
    
    • There SHOULD be a Root-Namespace to avoid collisions

    e.g: /Path1/Path2/Example.php with root:

    namespace APP\Path1\Path2;
    class Example {}
    
    • NEVER use manually defined path or directory lists, just point the loader to the top most directory
    • Keep the loader AS FAST AS POSSIBLE (because including a file is expensive enough)

    With this in mind, i produced the following script:

    function Loader( $Class ) {
        // Cut Root-Namespace
        $Class = str_replace( __NAMESPACE__.'\\', '', $Class );
        // Correct DIRECTORY_SEPARATOR
        $Class = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, __DIR__.DIRECTORY_SEPARATOR.$Class.'.php' );
        // Get file real path
        if( false === ( $Class = realpath( $Class ) ) ) {
            // File not found
            return false;
        } else {
            require_once( $Class );
            return true;
        }
    }
    

    Where to place it..

    • /Loader.php <-- there goes the loader
    • /Controller/... <-- put ur stuff here
    • /Model/... <-- or here, etc
    • /...

    Remeber:

    • if you use a root namespace, the loader has to be in this namespace too
    • you may prefix $Class to match your needs (controller_base {} -> class_controller_base.php)
    • you may change __DIR__ to an absolute path containing your class files (e.g. "/var/www/classes")
    • if you don't use namespaces, all files has to be in the same directory together with the loader (bad!)

    Happy coding ;-)


    A little review at other answers: THIS IS JUST MY PERSONAL OPINION - NO OFFENSE INTENDED!

    https://stackoverflow.com/a/5280353/626731 @alex good solution, but don't make you class names pay for bad file structures ;-) this is job for namespaces

    https://stackoverflow.com/a/5280510/626731 @Mark-Eirich it works, but its pretty nasty/ugly/slow/stiff[..] style to do it this way..

    https://stackoverflow.com/a/5284095/626731 @tealou for his problem to be solved this is the most clear approach so far :-) ..

    https://stackoverflow.com/a/9628060/626731 @br3nt this reflects my point of view, but please(!) .. dont use strtr!! .. which brings me to:

    https://stackoverflow.com/a/11866307/626731 @Iscariot .. to you, a little "you-know-bullshit-benchmark:

    Time        sprintf preg_replace strtr    str_replace v1 str_replace v2
    08:00:00 AM 1.1334  2.0955       48.1423  1.2109         1.4819
    08:40:00 AM 1.0436  2.0326       64.3492  1.7948         2.2337
    11:30:00 AM 1.1841  2.5524       62.0114  1.5931         1.9200
    02:00:00 PM 0.9783  2.4832       52.6339  1.3966         1.4845
    03:00:00 PM 1.0463  2.6164       52.7829  1.1828         1.4981
    Average     1.0771  2.3560       55.9839  1.4357         1.7237
    
    
    Method         Times Slower (than sprintf)
    preg_replace   2.19
    strtr          51.97
    str_replace v1 1.33
    str_replace v2 1.6
    

    Source: http://www.simplemachines.org/community/index.php?topic=175031.0

    Questions?.. (But he is in fact right about full path including)

    https://stackoverflow.com/a/12548558/626731 @Sunil-Kartikey https://stackoverflow.com/a/17286804/626731 @jurrien

    NEVER loop in time critical environment! Don't search for files on os! - SLOW

    https://stackoverflow.com/a/21221590/626731 @sagits .. much better than Marks ;-)

    0 讨论(0)
提交回复
热议问题