PSR4自动加载不使用Composer

9

我在项目中有一个包,使用composer自动加载,composer.json的条目如下:

 "autoload": {
      "psr-4": {
        "CompanyName\\PackageName\\": "packages/package-folder/src/"
    }
  }

现在我正在将这个项目复制到另一个不使用composer的项目中。如何在那里自动加载相同的包?

如果您有一个composer.json文件,您只能使用composer来查找包并将它们加载到您的项目中。 - Katie
但是这个并不在Composer仓库中。它是一个自定义的仓库,并且使用Composer的自动加载功能进行自动加载。 - Happy Coder
您可以尝试直接使用自动加载:http://php.net/manual/zh/function.autoload.php - Katie
但是我该如何为所有类执行此操作?在composer中,我正在提供文件夹路径。这里需要递归进行吗? - Happy Coder
你可以使用自定义仓库(zip、git 等)使其正常工作。请参阅以下文档:https://getcomposer.org/doc/05-repositories.md - drodil
3个回答

23

你需要阅读`composer.json`中定义的每个命名空间,手动加载相应的类。

以下是具体步骤:

function loadPackage($dir)
{
    $composer = json_decode(file_get_contents("$dir/composer.json"), 1);
    $namespaces = $composer['autoload']['psr-4'];

    // Foreach namespace specified in the composer, load the given classes
    foreach ($namespaces as $namespace => $classpaths) {
        if (!is_array($classpaths)) {
            $classpaths = array($classpaths);
        }
        spl_autoload_register(function ($classname) use ($namespace, $classpaths, $dir) {
            // Check if the namespace matches the class we are looking for
            if (preg_match("#^".preg_quote($namespace)."#", $classname)) {
                // Remove the namespace from the file path since it's psr4
                $classname = str_replace($namespace, "", $classname);
                $filename = preg_replace("#\\\\#", "/", $classname).".php";
                foreach ($classpaths as $classpath) {
                    $fullpath = $dir."/".$classpath."/$filename";
                    if (file_exists($fullpath)) {
                        include_once $fullpath;
                    }
                }
            }
        });
    }
}

loadPackage(__DIR__."/vendor/project");

new CompanyName\PackageName\Test();

当然,我不知道你在PackageName中有哪些类。 /vendor/project是你的外部库被克隆或下载的位置。这是你拥有composer.json文件的地方。

注意:这仅适用于psr4自动加载。

编辑: 为一个命名空间添加多个类路径支持

编辑2: 我创建了一个Github存储库来处理这段代码,如果有人想要改进它。


9

是的,这个问题已经过去6个月了,然而我刚使用了以下方法。 我找到了以下解决方法。我只需在项目文件夹中本地运行命令 composer dump-autoload -o。之后,我只需要上传 ./vendor/composer 文件夹和 /vendor/autoload.php 的内容到服务器上,就可以再次工作了。 如果您无法在服务器上运行 composer,则这很有帮助。


1
这并不是完全相同的问题。OP要求在没有composer的情况下处理composer.json中的autoload。 - Thibault
1
这仍然是一个有用且相关的评论。因为我正要在我开发的插件中面对这个问题。我的搜索正好带我来到这里。虽然你的答案是正确和有效的,但这个答案也是如此。因为当用户安装我的插件并且无法运行composer时,自动加载仍然必须工作。所以知道我可以在本地完成这个并且无需担心部署,非常有帮助。 - Daniel Böttner

4

出于多种原因,我不太喜欢Composer。第一个原因是共享主机服务没有将Composer作为软件包提供,因此很难交付低成本的应用程序或简单的MVC自定义框架。以下是符合PSR4标准的解决方法。

假设您在根目录中的文件中添加了此自动加载方法,并且我们正在自动加载名为“src”的文件夹中的所有类,以下是如何实现此目标的方法。

define('ROOT', dirname(__DIR__));
define('SLASH', DIRECTORY_SEPARATOR);

spl_autoload_register(function ($className) 
{
    $fileName = sprintf("%s%ssrc%s%s.php", ROOT, SLASH, SLASH, str_replace("\\", "/", $className));

    if (file_exists($fileName)) 
    {
        require ($fileName);
    } 
    else 
    {
        echo "file not found {$fileName}";
    }
});

现在每个文件都应该添加命名空间,如果有依赖,则使用它。以下是一个基本示例:

namespace myapp;
use Core\Example;

此外,在我的示例中,src内的所有文件夹名称都应以大写字母开头。
完成了。感谢@jerryurenaa的支持。

我三年前问过,现在忘记了情境。不管怎样,感谢你的回答。 - Happy Coder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接