来自不同文件夹的自动加载类

lau*_*kok 42 php oop autoload

这是我自动加载我controllers文件夹中的所有类的方法,

# auto load controller classes
    function __autoload($class_name) 
    {
        $filename = 'class_'.strtolower($class_name).'.php';
        $file = AP_SITE.'controllers/'.$filename;

        if (file_exists($file) == false)
        {
            return false;
        }
        include ($file);
    }
Run Code Online (Sandbox Code Playgroud)

但我也有models文件夹中的课程,我也想自动加载它们 - 我该怎么办?我应该复制上面的自动加载,只是改变路径models/(但不是重复?)?

谢谢.

编辑:

这些是我在控制器文件夹中的类文件名:

class_controller_base.php
class_factory.php
etc
Run Code Online (Sandbox Code Playgroud)

这些是我在模型文件夹中的类文件名:

class_model_page.php
class_model_parent.php
etc
Run Code Online (Sandbox Code Playgroud)

这就是我通常命名我的控制器类的方法(我使用下划线和低位),

class controller_base 
{
...
}

class controller_factory
{
...
}
Run Code Online (Sandbox Code Playgroud)

这就是我通常命名我的模型类的方法(我使用下划线和lowcaps),

class model_page 
    {
    ...
    }

    class model_parent
    {
    ...
    }
Run Code Online (Sandbox Code Playgroud)

br3*_*3nt 62

我看到你正在使用controller_*****model_*****作为类命名约定.

我读了一篇很棒的文章,它提出了一个使用php的替代命名约定namespace.

我喜欢这个解决方案,因为我把课程放在哪里并不重要.该__autoload会无论发现它是在我的文件结构.它还允许我随意调用我的课程.我的代码不需要类命名约定.

例如,您可以设置文件夹结构,如:

  • 应用/
    1. 控制器/
      • Base.php
      • Factory.php
    2. 楷模/
      • page.php文件
      • Parent.php

您的课程可以像这样设置:

<?php
namespace application\controllers;
class Base {...}
Run Code Online (Sandbox Code Playgroud)

和:

<?php
namespace application\models;
class Page {...}
Run Code Online (Sandbox Code Playgroud)

自动加载器可能看起来像这样(或者在最后看到'关于自动加载的说明'):

function __autoload($className) {
    $file = $className . '.php';
    if(file_exists($file)) {
        require_once $file;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后......你可以用三种方式调用类:

$controller = new application\controllers\Base();
$model = new application\models\Page();
Run Code Online (Sandbox Code Playgroud)

要么,

<?php
use application\controllers as Controller;
use application\models as Model;

...

$controller = new Controller\Base();
$model = new Model\Page();
Run Code Online (Sandbox Code Playgroud)

要么,

<?php
use application\controllers\Base;
use application\models\Page;

...

$controller = new Base();
$model = new Page();
Run Code Online (Sandbox Code Playgroud)

编辑 - 关于自动加载的说明:

我的主要自动装载机看起来像这样:

// 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;
});
Run Code Online (Sandbox Code Playgroud)

这个自动加载器是类名到目录结构的直接1:1映射; 命名空间是目录路径,类名是文件名.所以application\controllers\Base()上面定义的类将加载文件www/application/controllers/Base.php.

我将自动加载器放入一个文件bootstrap.php,它位于我的根目录中.这可以直接包含,也可以将php.ini修改为auto_prepend_file,以便在每个请求中自动包含它.

通过使用spl_autoload_register,您可以注册多个自动加载功能,以任何方式加载类文件.即,您可以将一些或所有类放在一个目录中,或者可以将一些或所有命名空间类放在一个文件中.非常灵活:)


ale*_*lex 27

您应该为类命名,以便下划线(_)转换为目录分隔符(/).一些PHP框架就是这样做的,比如Zend和Kohana.

所以,你为你的班级命名Model_Article并将文件放入classes/model/article.php,然后你的自动加载确实......

function __autoload($class_name) 
{
    $filename = str_replace('_', DIRECTORY_SEPARATOR, strtolower($class_name)).'.php';

    $file = AP_SITE.$filename;

    if ( ! file_exists($file))
    {
        return FALSE;
    }
    include $file;
}
Run Code Online (Sandbox Code Playgroud)

另请注意,您可以使用spl_autoload_register()任何功能进行自动加载功能.它也更灵活,允许您定义多个自动加载类型功能.

如果必须有多个自动加载功能,spl_autoload_register()允许这样做.它有效地创建了一个自动加载功能队列,并按照它们的定义顺序遍历每个功能.相比之下,__ autoload()只能定义一次.

编辑

注意: 自PHP 7.2.0起,__ autoload已被弃用.非常不鼓励依赖此功能.有关更多详细信息,请参阅PHP文档.http://php.net/manual/en/function.autoload.php


Der*_*rDu 7

我必须提一下"好"的自动加载脚本和代码结构,所以请仔细阅读以下内容


记住:

  • Classname ===文件名
  • 每个文件只有一个类

例如:Example.php包含

class Example {}
Run Code Online (Sandbox Code Playgroud)
  • 命名空间===目录结构

例如:/Path1/Path2/Example.php匹配

namespace Path1\Path2;
class Example {}
Run Code Online (Sandbox Code Playgroud)
  • 应该是一个Root-Namespace来避免冲突

例如:/Path1/Path2/Example.php with root:

namespace APP\Path1\Path2;
class Example {}
Run Code Online (Sandbox Code Playgroud)
  • 切勿使用手动定义的路径或目录列表,只需将加载程序指向最顶层的目录即可
  • 保持加载程序AS FAST AS POSSIBLE(因为包含文件足够昂贵)

考虑到这一点,我制作了以下脚本:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在哪里放置..

  • /Loader.php < - 加载器
  • / Controller/... < - 把你的东西放在这里
  • / Model/... < - 或者这里等
  • / ...

Remeber:

  • 如果使用根命名空间,则加载程序也必须位于此命名空间中
  • 您可以为$ Class添加前缀以满足您的需求(controller_base {} - > class_controller_base.php)
  • 您可以将__DIR__更改为包含类文件的绝对路径(例如"/ var/www/classes")
  • 如果你不使用命名空间,所有文件必须与加载器一起在同一目录中(坏!)

快乐的编码;-)


其他答案的一点评论: 这只是我的个人意见 - 没有意图!

/sf/answers/369624741/ @alex很好的解决方案,但不要让你的类名为坏文件结构付费;-)这是命名空间的工作

/sf/answers/369635731/ @Mark-Eirich它的工作原理,但这种方式非常讨厌/丑陋/缓慢/僵硬[...]风格..

/sf/answers/369886681/ @tealou要解决他的问题这是迄今为止最明确的方法:-) ..

/sf/answers/673964231/ @ br3nt这反映了我的观点,但请(!)..不要使用strtr !! ..带我到:

/sf/answers/830641521/ @Iscariot ..给你,一点点"你知道废话基准:

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
Run Code Online (Sandbox Code Playgroud)

资料来源:http://www.simplemachines.org/community/index.php? topic = 175031.0

有问题吗?..(但他实际上是完全正确的道路,包括)

/sf/answers/878399091/ @Sunil-Kartikey /sf/answers/1210076311/ @jurrien

永远不要在时间关键环境中循环!不要在os上搜索文件!- 慢

/sf/answers/1485511331/ @sagits ..比Marks好多了;-)