【问题标题】:How to force Composer script to load local class instead of global class如何强制 Composer 脚本加载本地类而不是全局类
【发布时间】:2018-10-12 23:10:44
【问题描述】:

未定义的方法

(相关文件链接在我的问题底部。)

我让 Composer 运行一些 post-install-cmdpost-update-cmd 脚​​本。在我的脚本中,我想使用来自symfony/filesystemreadlink() 函数。在我的项目/vendor 文件夹中有3.4 版本的文件系统包,很好。

我在文件顶部use Symfony\Component\Filesystem\Filesystem;

但每当我跑步时:

$fs = new Filesystem();
$path = '/path/to/some/symlink';
if ($fs->readlink($path)) {
  // code
}

我收到以下错误,告诉我我正在调用未定义的方法:

PHP 致命错误:未捕获的错误:调用未定义的方法 Symfony\Component\Filesystem\Filesystem::readlink() 在 /Users/leymannx/Sites/blog/scripts/composer/ScriptHandler.php:160

好的,所以我仔细检查了项目的 /vendor 文件夹中的类。这个方法是有的。我的 IDE 将我指向那里。但是当我运行时:

$fs = new Filesystem();
get_class_methods($fs);

此方法未列出。

它试图从哪个文件加载方法?

好的,所以我试着检查它从哪个文件加载这个类:

$fs = new Filesystem();
$a = new \ReflectionClass($fs);
echo $a->getFileName();

然后返回给我phar:///usr/local/Cellar/composer/1.7.2/bin/composer/vendor/symfony/filesystem/Filesystem.php – 但是为什么呢?为什么它从我的 Mac 的酒窖中取出包裹?这很奇怪。

但是好的,所以我认为这是 Homebrew 问题,并卸载了 Homebrew Composer $ brew uninstall --force composer 并再次安装为 PHAR,如 https://getcomposer.org/doc/00-intro.md#globally 中所述。

但现在都一样了。

$fs = new Filesystem();
$a = new \ReflectionClass($fs);
echo $a->getFileName();

回复我phar:///usr/local/bin/composer/vendor/symfony/filesystem/Filesystem.php

但是为什么呢?为什么它会从我的全局 Composer 安装中获取(过时的)包?如何强制我的脚本使用项目的本地类,而不是全局 Composer 安装中的类?

还有什么?

最初我的$PATH 包含/Users/leymannx/.composer/vendor/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin。我删除了/Users/leymannx/.composer/vendor/bin,只返回/usr/local/bin /usr/bin /bin /usr/sbin /sbin。还是一样。

我还尝试在我的composer.json 中设置以下内容。还是一样:

"optimize-autoloader": true,
"classmap-authoritative": true,
"vendor-dir": "vendor/",

我终于在 GitHub 上创建了一个问题:https://github.com/composer/composer/issues/7708


【问题讨论】:

    标签: php symfony composer-php


    【解决方案1】:

    这是运行代码的上下文问题。如果您直接在post-install-cmd 中执行某些方法,它将在 Composer 的进程中执行。这意味着它将共享捆绑在composer.phar 中的所有代码。由于不能有两个具有相同 FQN 的类,因此不能在此上下文中包含另一个 Symfony\Component\Filesystem\Filesystem

    您可以通过在单独的进程中运行脚本来绕过此问题。您可以创建 post-install-cmd.php 文件,在其中执行所有引导(如需要 vendor/autoload.php)并调用这些方法。然后在你的 post-install-cmd 钩子中运行这个文件:

    "scripts": {
        "post-install-cmd": [
            "php post-install-cmd.php"
        ]
    },
    

    【讨论】:

    • 最后通过在我的脚本顶部要求 require_once __DIR__.'/../vendor/autoload.php' 并保持其他所有内容不变来修复它。
    猜你喜欢
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    相关资源
    最近更新 更多