命令行

composer dump 能跑,因为 symfony/console 允许 unambiguous prefix —— 任何 composer 子命令都可缩到能唯一匹配的最短前缀:

composer dump              # = dump-autoload
composer i                 # = install
composer show --platform   # 列本机 platform package(php / ext-* / lib-*)

--prefer-install=source|dist|auto 是 install / update 的同名 flag;--prefer-source / --prefer-dist 是它的快捷写法,三者底层同一开关。

发包瘦身

dist tarball 默认把 repo 里所有文件打进去(demo / test / CI 配置)。.gitattributesexport-ignore 把它们排除出 dist:

/demo            export-ignore
phpunit.xml.dist export-ignore
/.github/        export-ignore

本地 git archive 预览实际 dist 包内容:

git archive HEAD --format zip -o preview.zip

几个反直觉默认

Config默认
process-timeout300s装大包(satis 全量索引、monorepo)容易 5 分钟撞 timeout
platform-checkphp-only只查 PHP 版本,不查扩展。缺扩展要等运行时 Call to undefined function 才暴露
discard-changesfalsesource 装的包本地有改动时 update 会卡 prompt;CI 设 truestash
preferred-installauto可以 per-package 配,自家 fork 走 source 方便 patch,其余走 dist
{
    "config": {
        "process-timeout": 900,
        "preferred-install": {
            "myorg/*": "source",
            "*": "dist"
        }
    }
}

生产环境 autoload 优化

composer install --no-dev 是基操,再加:

  • -o / --optimize-autoloader:把 PSR-4 规则转成 classmap,避免运行时按规则扫文件系统
  • -a / --classmap-authoritative:autoloader 只信 classmap,不再 fallback 到文件系统 stat。隐式包含 -o

-a-o 更激进:classmap 没收录的类(运行期动态 include 老代码)会找不到。常规 Laravel / Symfony 应用是安全的。

运行时探查

Composer\InstalledVersions 在 Composer 2.0+ 全程可用,比读 composer.lock 干净:

use Composer\InstalledVersions;
use Composer\Semver\VersionParser;

InstalledVersions::isInstalled('vendor/package');             // bool
InstalledVersions::isInstalled('psr/log-implementation');     // virtual package(实现了 psr/log 的任意包)
InstalledVersions::isInstalled('vendor/package', false);      // 仅查 require,跳过 require-dev(2.1+)

InstalledVersions::satisfies(new VersionParser, 'vendor/package', '^2.0');
InstalledVersions::getVersion('vendor/package');              // 标准化版本,如 1.2.3.0
InstalledVersions::getPrettyVersion('vendor/package');        // 原始字串,如 v1.2.3
InstalledVersions::getInstallPath('vendor/package');          // 绝对路径
InstalledVersions::getInstalledPackagesByType('foo-plugin');  // 按 composer.json 的 type 字段筛

写插件 / 探测可选依赖时 isInstalled('psr/log-implementation')class_exists(LoggerInterface::class) 准 —— 后者会被 IDE / opcache stub 干扰。

composer-installed bin script 里定位资源

写在 composer.jsonbin 字段被装到 vendor/bin/ 后,找回项目的 vendor/autoload.php 传统要 dirname(__DIR__, N) 往上猜目录,被装在不同深度就要重写。Composer 2.2+ 注入两个全局变量解决:

#!/usr/bin/env php
<?php
require $_composer_autoload_path;   // 装它的项目的 vendor/autoload.php
$binDir = $_composer_bin_dir;       // 装它的项目的 vendor/bin

参考