【问题标题】:PSR4 auto load without composer没有作曲家的 PSR 4 自动加载
【发布时间】:2017-01-27 00:55:02
【问题描述】:

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

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

现在我将其复制到另一个未使用 composer 的项目中。我怎样才能在那里自动加载相同的包?

【问题讨论】:

  • 如果你有composer.json文件,你只能使用composer查找包并加载到你的项目中。
  • 但这不在作曲家存储库中。它是一个自定义存储库,并使用 composer 的自动加载功能自动加载。
  • 你可以试试直接自动加载:php.net/manual/en/function.autoload.php
  • 但我怎样才能为所有课程做到这一点?在作曲家中,我给出了文件夹路径。在这里我需要递归吗?
  • 您可以使其与自定义存储库(zip、git 等)一起使用。请参阅以下文档:getcomposer.org/doc/05-repositories.md

标签: php composer-php autoload


【解决方案1】:

您必须阅读作曲家并自己为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 自动加载。

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

EDIT2 :如果有人想改进它,我创建了一个Github repo 来处理此代码。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这不是同一个问题。 OP 要求在根本没有作曲家的情况下处理来自 composer.json 的自动加载。
    • 这仍然是一个有用且相关的评论。因为我即将在我开发的插件中遇到这个问题。我的搜索把我带到了这里。虽然您的答案是正确有效的,但这个答案也是如此。因为当用户安装我的插件并且无法运行composer时,自动加载仍然必须工作。因此,知道我可以在本地执行此操作并无忧无虑地部署它,会很有帮助。
    【解决方案3】:

    出于多种原因,我不是 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

    【讨论】:

    • 三年前我问过。忘记剧情了。无论如何感谢您的回答
    猜你喜欢
    • 1970-01-01
    • 2016-03-31
    • 2016-10-24
    • 2019-09-22
    • 2017-01-02
    • 2017-07-15
    • 2019-01-31
    • 2017-06-23
    • 2016-10-31
    相关资源
    最近更新 更多