编写器/PHP:如何检查composer包是否安装?

ghhaqwfi  于 2023-01-29  发布在  PHP
关注(0)|答案(3)|浏览(362)

在我们的应用程序中使用PHP,检查一个包(任何版本)是否安装/存在的最干净的方法是什么?
基本上,在我们的应用程序中,我们希望调用一个具有以下签名的函数:
bool function hasComposerPackage(string $packageName)
这个函数需要包含什么才能执行以下操作:

if (hasComposerPackage('phpunit/phpunit')) {
    echo 'PHPUnit is installed!';
}

理想情况下,这需要在没有任何命令行exec调用的情况下进行,并且不应该在过程中自动加载任何 * 不必要的 * 文件。

1szpjjfi

1szpjjfi1#

Composer 2(2020年10月)现在支持查找软件包安装状态!https://blog.packagist.com/composer-2-0-is-now-available/
有一个新的类Composer\InstalledVersions,它在每个项目中自动加载,并且在运行时可用。它允许您检查在您自己的项目运行时存在哪些包/版本。
以下用法示例来自 * 已安装版本- Runtime Composer实用程序 *:

\Composer\InstalledVersions::isInstalled('vendor/package'); // returns bool

@user1132363使用shell_exec()来运行类似composer show的东西是唯一确定的方法(Composer低于2),但你似乎拒绝想走这条路。我不知道你为什么拒绝,这是你的问题的解决方案。没有其他可靠的方法。使用class_exists也是不可靠的,因为类名称可以在包中更改。
话虽如此,我认为还有一个更大的问题你没有问:你 * 实际上 * 试图解决什么问题?就像,为什么你需要检查一个包是否安装了?

lp0sw83n

lp0sw83n2#

这是一个老问题,我认为accepted answer是好的,但只是对于那些希望跨Composer版本移植的人,甚至可能在没有composer用户命令的系统上部署,并且还希望了解文件系统的底层协议。
一般来说,您可以在安装 * 之后 * 从您自己的软件包中轻松获取供应商文件夹。

hakre/xmlreaderiterator
  • (示例性“自有”包在composer供应商文件夹中的相对路径,参考)*

此外,在安装 * 其他 * Composer配置的软件包 * 之后,* 您同样可以轻松获取它们的安装状态。

composer/semver
  • (另一个示例,Composer Semver,编写器供应商文件夹中的包相对路径,refs)*

像往常一样,我们可能“只”需要了解Composer本身如何与我们的(file-)系统,我在这里的回答中详细阐述了它,以突出您既不需要依赖于特定的Composer运行时版本,也不需要依赖于shell_exec(),因为我们已经在执行PHP代码,a)这是不必要的,B)我们可能没有composer(1)(名为 composer 的用户命令),以及c)我们可能没有composer.json的位置,也没有vendor文件夹的位置。
YMMV,对此我持保留态度,例如,如果我在构建时手头上有composer(1),我就不会强调文件系统的细节,但是我可能已经从了解installed.json文件中受益。
让我们看看vendor文件夹到底是什么,它在哪里,以及包是如何放置在里面的,然后通过包名获取任何包的安装状态:

  1. Composer安装(默认情况下,除非重写)所有依赖项(包)到 *vendor文件夹 * 中。这是一个中心配置选项,默认情况下为相对路径vendor。它相对于工作目录,默认情况下,composer将从该工作目录中的相对路径composer.json加载项目配置(用于composer更新命令)和composer.lock(用于composer安装命令,如果尚未禁用锁定文件)。
    1.可以更改这些设置,最突出的工作目录可能是COMPOSER环境参数的composer.json(和.lock),以及COMPOSER_VENDOR_DIR参数的vendor目录。
    1.正如前面在问题中所讨论的,这些环境参数还会覆盖项目composer.json配置文件中的配置设置:主要是#/config/vendor-dir,但也包括具有或不具有锁定文件#/config/lock的行为(#之后的所有JSON指针相对于$COMPOSER_HOME/config.json的JSON文本合并生成进行标记,并覆盖$COMPOSER)。
    1.因此,如果您不想依赖运行时(例如,没有shell_exec()),则必须自己找出供应商目录。
    1.供应商目录只能在安装 * composer之后才能计算出来,如1.)中所述,它将创建 *vendor文件夹 *。
    1.拥有一个由composer安装的软件包可以让你找到安装在 *vendor文件夹 * 中的文件。在PHP中,你可以通过__DIR__magic constant获取文件本身的路径。
    1.软件包在 *vendor文件夹 * 中的默认安装位置是 * 软件包名称 *。这也是为什么它应该全部小写并且只包含简化文件名字符集中的字符的原因:这样更便于移植,有助于您在 *vendor文件夹 * 中轻松查找软件包。
    1.*vendor文件夹 * 中软件包的默认位置是package-vendor-name/package-name-name目录,每个软件包的默认位置是composer.json#/name,例如,从 *vendor文件夹 * */*/composer.json#/name的根目录开始。
    1.在您自己的代码中,您已经配置为与composer一起安装,并且您已经与composer一起安装了它,那么代码就可以从它自己的文件的__DIR__魔术常数中获得到 *vendor文件夹 * 的绝对路径,方法是获取层次结构中的祖父目录。例如,假设您的php文件在项目的根目录中,dirname(__DIR__, 2)(或者dirname(dirname(dirname(__FILE__))),如果你需要这样的兼容性,对于7.0/5.3以下的PHP版本--Composers默认的自动加载器代码也支持它,顺便说一句,它与PHP 5.2兼容,所以在这个细节层次上,你 * 可能 * 想要支持它)。
    1.现在,在建立了 *vendor文件夹 * 的绝对路径之后,您可以通过文件夹查找其他软件包(与处理包和祖目录查找的方式相反),只需知道名称,-或-,通过定位composer/installed.json,它是composer install命令调用的合成器标记文件,“*vendor文件夹”也安装了您的软件包。它的形式在历史上确实发生了变化,但变化不大。虽然我们已经走到了这一步,但这不应该是一个阻碍。
    安装(生成)时供应商文件夹中的非默认位置:
  • vendor文件夹仅仅是一个目录,并且在Composer安装之后,例如通过hook脚本或者仅仅因为你可以这样做,其中的文件可以自由地重新排列。

  • composer/installed.json文件的好处是Composer本身保留了它在vendor文件夹中安装的协议。因此,尽管有些东西从默认位置移走了,但只要这个文件没有被移动,您通常就可以依赖它。Composer也是如此。

  • 在Composer用于安装(创建和填充vendor文件夹)的文件上,您可能并不总是看到更改的时间戳,因为它依赖于composer/installed.json文件来确定vendor文件夹的内容,并且如果它认为vendor文件夹生成已经完成,则不会更新。

  • 当您希望有一个干净的供应商文件夹生产时,您可以很容易地防止运行带有--no-scripts--no-plugins标志的composer命令的脚本,对于仅生产的供应商,可能使用--no-dev

  • 您可以轻松地基于composer/installed.json创建自己的供应商文件夹sentinel,方法是强制复制该文件夹,同时还将为您提供更新的时间戳。

  • 您可以通过在vendor文件夹中复制composer.json和composer.lock(如果正在使用)并设置COMPOSER环境参数来进一步创建sentinel。这样做的好处是,仍然可以对所有这些文件无效vendor文件夹,并获得额外的簿记。

通常每个项目都是不同的,因此你可能只想从这个答案中挑选一个细节,甚至相反,你可能不想在你了解它 * 之后 * 使用它。只依赖composer的命令行界面并在之后拥有你的项目依赖项和自动加载器是相当有好处的。
通过在composer.json中指定所需的包,您知道默认安装哪些包。Composer可以安装它们(您知道这些包在那里),也可以安装失败(您知道这些包不在那里)。

hl0ma9xz

hl0ma9xz3#

实际上你可以使用PHP的class_exists()函数。你只需要知道名称空间,我建议你把它作为一个字符串而不是ClassName::class来使用。

<?php

class_exists('romanzipp\QueueMonitor\Services\QueueMonitor');

如果您使用的是composer自动加载,则返回true或false。

相关问题