如何自动加载PHP类?

时间:2015-07-07 19:50:53

标签: php wordpress autoload spl-autoload-register

我正在使用Wordpress的课程,我正在尝试在我的functions.php文件中自动加载它们:

spl_autoload_register(function($class) {
    include('classes/'.$class.'.php');
});

这是我的classes目录:

  • 类/
    • 项目/
      • Application.php
      • core.php中
      • Site.php
      • Helpers.php
    • utils的/
      • Helpers.php
      • Twig.php
    • 视图/
      • layout.php中
      • Modules.php
      • 页/
        • Home.php

每个类都根据它所在的目录进行命名空间。例如:

$homeClass = new \views\pages\Home();

当我自动加载类时,我收到此错误:

  

PHP警告:include(classes / project \ Application.php):无法打开流:没有这样的文件或目录

显然,作为命名空间一部分的反斜杠不能在路径中工作。我可以更新我的函数来用正斜杠替换反斜杠,如下所示:

spl_autoload_register(function($class) {
    include('classes/'.str_replace("\\", "/", $class).'.php');
});

但这似乎很奇怪。我错过了什么吗?

4 个答案:

答案 0 :(得分:1)

我在这里有一个例子 基本上是一个更好的spl_autoload_register版本,因为它只会在你初始化类时尝试要求类文件。
在这里,它会自动获取类文件夹中的每个文件,需要文件并对其进行初始化。您所要做的就是将类命名为与文件相同 的的index.php

<?php
require_once __DIR__ . '/app/autoload.php';

$loader = new Loader(false);

User::dump(['hello' => 'test']);

<强> autoload.php

<?php
class Loader 
{

    public static $library;

    protected static $classPath = __DIR__ . "/classes/";

    protected static $interfacePath = __DIR__ . "/classes/interfaces/";

    public function __construct($requireInterface = true) 
    {
        if(!isset(static::$library)) {
            // Get all files inside the class folder
            foreach(array_map('basename', glob(static::$classPath . "*.php", GLOB_BRACE)) as $classExt) {
                // Make sure the class is not already declared
                if(!in_array($classExt, get_declared_classes())) {
                    // Get rid of php extension easily without pathinfo
                    $classNoExt = substr($classExt, 0, -4); 
                    $file = static::$path . $classExt;

                    if($requireInterface) {
                        // Get interface file
                        $interface = static::$interfacePath . $classExt;
                        // Check if interface file exists
                        if(!file_exists($interface)) {
                            // Throw exception
                            die("Unable to load interface file: " . $interface);
                        }

                        // Require interface
                        require_once $interface;
                        //Check if interface is set
                        if(!interface_exists("Interface" . $classNoExt)) {
                            // Throw exception
                            die("Unable to find interface: " . $interface);
                        }
                    }

                    // Require class
                    require_once $file;
                    // Check if class file exists
                    if(class_exists($classNoExt)) {
                        // Set class        // class.container.php
                        static::$library[$classNoExt] = new $classNoExt();
                    } else {
                        // Throw error
                        die("Unable to load class: " . $classNoExt);
                    }

                }
            }
        }
    }

    /*public function get($class) 
    {
        return (in_array($class, get_declared_classes()) ? static::$library[$class] : die("Class <b>{$class}</b> doesn't exist."));
    }*/
}

您可以轻松管理一些编码,也可以要求不同文件夹中的类。希望这对你有用。

答案 1 :(得分:0)

It's not odd at all!

使用命名空间注册自动加载器作为表示目录结构的方法是很常见的做法。我建议关注PSR-4 conventions,但是如果你在重构命名约定方面太过分,那么我建议使用DIRECTORY_SEPARATOR常量来帮助PHP决定是否使用'/'或'\ ',因为Windows服务器使用后者,Linux服务器使用前者。

答案 2 :(得分:0)

我已经为这个要求做了一个课程,与PSR-4兼容。

你可以在这里联系到它: https://github.com/pablo-pacheco/wp-namespace-autoloader

解释就在那里,但基本上它是作曲家的依赖。您只需在项目中要求它:

"require": {    
    "pablo-pacheco/wp-namespace-autoloader": "dev-master"
}

然后调用类

<?php
new \WP_Namespace_Autoloader( array(    
    'directory'   => __DIR__,       // Directory of your project. It can be your theme or plugin. __DIR__ is probably your best bet.    
    'namespace'   => __NAMESPACE__, // Main namespace of your project. E.g My_Project\Admin\Tests should be My_Project. Probably if you just pass the constant __NAMESPACE__ it should work     
    'classes_dir' => 'src',         // (optional). It is where your namespaced classes are located inside your project. If your classes are in the root level, leave this empty. If they are located on 'src' folder, write 'src' here 
) );

我感谢任何反馈!

答案 3 :(得分:0)

尝试此类,它将自动加载with or without namespaces