Composer 自动加载而不是自动加载

问题描述 投票:0回答:1

简而言之,Composer 为我制作的自动生成的 autoload.php 实际上并未加载任何内容。

我以前用过Composer安装过别人的项目,但这是我第一次用它来管理自己项目中的依赖关系。

这是我的

composer.json
。为了保护无辜者,名字已更改:

{
    "name": "MyWorkplace/MyApp",
    "description": "A very cool doohickey.",
    "authors": [
        {
            "name": "wdmartin",
            "email": "[email protected]"
        }
    ],
    "require": {
        "onelogin/php-saml": "4.1.*"
    }
}

输入该要求行后,我运行了

composer update
。它下载了 php-saml 库及其依赖项 xmlseclibs,并生成了一个 autoload.php 文件。

所以我开始处理项目中的第一个文件,如下所示:

<?php
require_once('vendor/autoload.php');

use OneLogin\Saml2\Settings;

// settings.php just creates the $settingsInfo array.
require_once('settings.php');

$settings = new Settings($settingsInfo, true);

运行代码会产生错误:

Fatal error: Uncaught Error: Class "OneLogin\Saml2\Settings" not found

自动加载器显然没有自动加载类定义。

我尝试将

autoload.php
的输出保存到变量中并将其转储,这给了我这样的结果:

object(Composer\Autoload\ClassLoader)#1 (11) {
  ["vendorDir":"Composer\Autoload\ClassLoader":private]=>
  string(24) "/var/www/html/vendor"
  ["prefixLengthsPsr4":"Composer\Autoload\ClassLoader":private]=>
  array(2) {
    ["R"]=>
    array(1) {
      ["RobRichards\XMLSecLibs\"]=>
      int(23)
    }
    ["O"]=>
    array(1) {
      ["OneLogin\"]=>
      int(9)
    }
  }
  ["prefixDirsPsr4":"Composer\Autoload\ClassLoader":private]=>
  array(2) {
    ["RobRichards\XMLSecLibs\"]=>
    array(1) {
      [0]=>
      string(63) "/var/www/html/vendor/composer/../robrichards/xmlseclibs/src"
    }
    ["OneLogin\"]=>
    array(1) {
      [0]=>
      string(58) "/var/www/html/vendor/composer/../onelogin/php-saml/src"
    }
  }
  ["fallbackDirsPsr4":"Composer\Autoload\ClassLoader":private]=>
  array(0) {
  }
  ["prefixesPsr0":"Composer\Autoload\ClassLoader":private]=>
  array(0) {
  }
  ["fallbackDirsPsr0":"Composer\Autoload\ClassLoader":private]=>
  array(0) {
  }
  ["useIncludePath":"Composer\Autoload\ClassLoader":private]=>
  bool(false)
  ["classMap":"Composer\Autoload\ClassLoader":private]=>
  array(1) {
    ["Composer\InstalledVersions"]=>
    string(67) "/var/www/html/vendor/composer/../composer/InstalledVersions.php"
  }
  ["classMapAuthoritative":"Composer\Autoload\ClassLoader":private]=>
  bool(false)
  ["missingClasses":"Composer\Autoload\ClassLoader":private]=>
  array(0) {
  }
  ["apcuPrefix":"Composer\Autoload\ClassLoader":private]=>
  NULL
}

我可以看到应该加载的类,但它们不存在。我尝试跑步

get_declared_classes()
;在总是加载的原生 PHP 类的巨大列表的末尾,我发现了以下三个条目:

[215]=>
string(54) "ComposerAutoloaderInita5339d1e68f4fc243101898f7cd6b2b7"
[216]=>
string(29) "Composer\Autoload\ClassLoader"
[217]=>
string(68) "Composer\Autoload\ComposerStaticInita5339d1e68f4fc243101898f7cd6b2b7"

所以自动加载器肯定是自动加载本身。但 OneLogin\Saml2 类不在列表中,它的依赖项 XMLSecLibs 也不在列表中。

我尝试手动编辑自动加载文件,让它们通过沿途转储一堆信息来告诉我它们在做什么,但是除了验证自动加载器代码实际上是否具有正确的路径之外,没有产生任何可用的信息库的文件夹。

这是我对此进行猛烈抨击的第二天。这可能是非常明显的事情,但我没有看到。我当然可以直接将代码与

require_once('vendor/onelogin/php-saml/src/Saml2/Settings.php');
之类的东西链接起来,但这首先就违背了使用 Composer 的目的。任何建议将不胜感激。

编辑:

composer show

的输出
onelogin/php-saml      4.1.0 OneLogin PHP SAML Toolkit
robrichards/xmlseclibs 3.1.1 A PHP library for XML Security

编辑2: AlexHowansky 请求的一些调试输出。我运行了这段代码:

header('Content-Type: text/plain');
require_once('vendor/autoload.php');

print "Class exists?:\n";
var_dump(class_exists(\OneLogin\Saml2\Settings::class));

print "\n\nIs it in the array of declared classes?\n";
var_dump(in_array(\OneLogin\Saml2\Settings::class, get_declared_classes()));

它生成以下输出:

Class exists?:
bool(false)


Is it in the array of declared classes?
bool(false)

此外,我还检查了所有文件权限,以防网络服务器无权读取它,它们看起来没问题。

php composer-php
1个回答
0
投票

您的配置和代码看起来不错,并且在 RHEL 9 docker 映像上可以正常工作。如果你跑步:

require_once('vendor/autoload.php');
var_dump(class_exists(\OneLogin\Saml2\Settings::class));
var_dump(in_array(\OneLogin\Saml2\Settings::class, get_declared_classes()));

并得到:

bool(false)
bool(false)

然后看起来要求工作正常,否则脚本将在此时中止并且永远不会运行 var_dump() 调用。这将得出两个结论:1) 您的 Web 服务器进程无法读取文件,2) 您已禁用错误报告。

您可以运行类似

chmod -R 775 vendor
的递归权限更改,但这可能过于宽松。理想情况下,您希望这些文件由运行 Web 服务器进程的用户以外的用户拥有,然后将权限最低限度设置为仅允许读取。
chmod -R 755 vendor
更可取。

要启用错误报告,请加载运行

phpinfo()
函数的页面。这将告诉您网络服务器进程正在使用哪个 INI 文件。请参阅其内容以了解以下值:

display_errors = On
display_startup_errors = On
error_reporting = E_ALL

注意,如果这只是一个开发服务器,我不确定我是否会费心使用 Apache,它(显然)增加的麻烦超过了它的价值。查看内置 Web 服务器,它对于本地开发来说已经足够了。我通常只是将这样的内容添加到我的

composer.json
文件中:

    "scripts": {
        "go": [
            "Composer\\Config::disableProcessTimeout",
            "php -S localhost:8000 -t public/"
        ]
    },

然后我可以使用

composer go
从 CLI 启动本地服务器。

© www.soinside.com 2019 - 2024. All rights reserved.