为什么 class 自动加载对使用 "repositories.package" 所需的包不起作用?

Why does class autoloading not work for a package required using "repositories.package"?

考虑两种情况:

第一个库是从 Github 加载的,composer.json 看起来像这样:

{
    "require": {
        "revenuewire/ach-file": "*"
    }
}

composer 库使用此命令下载:

php composer update

PHP代码:

<?php
require '../composer/vendor/autoload.php';
$achFileHeaderRecord = new \RW\ACH\FileHeaderRecord([
    // Required
    \RW\ACH\FileHeaderRecord::IMMEDIATE_DESTINATION => ' 123456789',
    \RW\ACH\FileHeaderRecord::IMMEDIATE_ORIGIN      => '1234567890',
    \RW\ACH\FileHeaderRecord::DESTINATION_NAME      => 'DESTNAME',
    \RW\ACH\FileHeaderRecord::ORIGIN_NAME           => 'Orig Name',
    // Optional
    \RW\ACH\FileHeaderRecord::FILE_DATE             => new DateTime(),
    \RW\ACH\FileHeaderRecord::FILE_ID_MODIFIER      => 'A',
    \RW\ACH\FileHeaderRecord::REFERENCE_CODE        => '',
]);
?>

此代码将 运行 成功。

但是当我尝试从 Gitlab 加载 完全 相同的库时,composer.json 看起来像这样:

{
    "repositories": [
      {
        "type": "package",
        "package": {
          "name": "mygitlab/ach-file",
          "version": "1.2",
          "type": "package",
          "source": {
              "url": "https://mygitlab.ca/mygitlab/ach-file.git",
              "type": "git",
              "reference": "master"
          }
        }
      }
    ],
    "require": {
        "mygitlab/ach-file": "*"
    }
}

现在 运行 相同的代码我得到这个错误:

PHP Fatal error: Uncaught Error: Class 'RW\ACH\FileHeaderRecord' not found

这是因为库没有自动加载。 可以通过添加这一行来解决,手动加载它:

require '../composer/vendor/aptpayapi/ach-file/bootstrap.php';

所以在它作为外部包加载的情况下,它不会 read/execute 库的 composer.json

{
    "name": "revenuewire/ach-file",
    "type": "library",
    "description": "Create and read ACH Payment files",
    "homepage": "https://github.com/revenuewire/ach-payment-file",
    "license": "Apache-2.0",
    "authors": [
        {
            "name": "Matthew Casiro",
            "email": "mattcasiro@gmail.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "RW\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "RW\Tests\": "tests/"
        }
    },
    "config": {
        "platform": {
            "php": "7"
        }
    },
    "require": {
        "ext-ssh2": "*",
        "ext-bcmath": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^6.5"
    }
}

是否可以强制自动加载外部加载的包?

你的问题是,通过为该存储库使用 package 键,你告诉作曲家“从 这里 读取包信息,不要读取托管的 composer.json”。并且由于 package 设置几乎是空的,依赖关系没有解决,自动加载器也没有生成。

唯一会发生的事情是作曲家在您的供应商中克隆了存储库,然后您就只能靠自己了。

可以 添加一个 autoload 部分到您当前的 package 键,如图 here 所示。这样你至少可以正确生成自动加载器。

但请注意,不会处理递归依赖解析,这可能会给您带来其他问题。

为此,您可以在 package 设置中复制原始 composer.jsonrequire 部分...但这并不明智。 package 键用于 不支持 Composer 的包,因此您可以强制它们在您的应用程序中支持它。你会以这样的方式结束:

{
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "mygitlab/ach-file",
        "version": "1.2",
        "type": "package",
        "autoload": {
          "psr-4": {
            "RW\": "src/"
          }
        }, 
         "require": {
                "ext-ssh2": "*",
                "ext-bcmath": "*"
            },
        "source": {
          "url": "https://mygitlab.ca/mygitlab/ach-file.git",
          "type": "git",
          "reference": "master"
        }
      }
    }
  ],
  "require": {
    "mygitlab/ach-file": "*"
  }
}

坦率地说,我不建议将此用于分叉的作曲家包。如果你想要的是使用现有包的分支,根本不要使用 package 键。

只需添加存储库配置,并按其原始名称要求分叉包(在本例中为revenuewire/ach-file)。将版本替换为 dev-master(或您用来存放叉子的任何分支),瞧,一切都会照常工作,因为该库将作为常规作曲家包需要。

{
 "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/yivi/ach-file"
        }
    ],
    "require": {
        "revenuewire/ach-file": "dev-master"
    }
}