【问题标题】:post-require hook in php composer not working when installing from packagist.org从 packagist.org 安装时,php composer 中的 post-require 钩子不起作用
【发布时间】:2026-01-05 11:20:05
【问题描述】:

可以使用composer require vendor/package-name 之类的命令从packagist.org 安装PHP 包。现在composer documentation 声明在作曲家执行期间有几个事件的钩子:

在 Composer 的术语中,脚本可以是 PHP 回调(定义为静态方法)或任何命令行可执行命令。脚本对于在 Composer 执行过程中执行包的自定义代码或包特定的命令很有用。

文档进一步说明:

注意:仅执行根包的 composer.json 中定义的脚本。如果根包的依赖项指定了自己的脚本,则 Composer 不会执行这些附加脚本。

这是否意味着当需要通过 composer require vendor/package-name 从 packagist.org 获取包时,无法执行 PHP 代码?

【问题讨论】:

  • 仅当您在需要包之前在主 composer.json 中手动放置一个 post 脚本时。因此,作为包维护者,您无法访问根目录,如果您可以加载和执行包之外的任何内容,这将是一个安全问题。

标签: php composer-php hook


【解决方案1】:

几年前在composer issue-queue 中就这个话题进行了相当长的讨论。

https://github.com/composer/composer/issues/1193

TLDRpost-update-cmd 钩子不支持它,但可以通过编写 composer 插件来解决这个问题。例如,我做了一个通用插件来为任何新的或更改的包运行 compile 钩子:

https://github.com/civicrm/composer-compile-plugin

文档中的示例:

{
  "name": "foo/bar",
  "require": {
    "civicrm/composer-compile-plugin": "~0.8",
    "scssphp/scssphp": "1.2.0",
    "padaliyajay/php-autoprefixer": "~1.2"
  },
  "autoload": {"psr-4": {"ScssExample\\": "src"}},
  "extra": {
    "compile": [
      {"run": "@php-method \\ScssExample\\ScssExample::make"}
    ]
  }
}

以及对应的回调:

namespace ScssExample;
class ScssExample
{
  public static function make(array $task)
  {
    $scssCompiler = new \ScssPhp\ScssPhp\Compiler();
    $scss = 'div { .foo { hyphens: auto; } }';
    $css = $scssCompiler->compile($scss);
    $autoprefixer = new \Padaliyajay\PHPAutoprefixer\Autoprefixer($css);
    file_put_contents("build.css", $autoprefixer->compile());
  }
}

【讨论】:

    【解决方案2】:

    composer 将在使用require 安装请求的包后发送post-update-cmd 事件。这将执行在您的根 composer.json 中为此事件定义的脚本。请参阅此示例场景:

    composer.json

    {
        "autoload": {
            "psr-4": {
                "fknffa\\": "src"
            }
        },
        "scripts": {
            "post-update-cmd": [
                "fknffa\\floom::sayHello"
            ]
        }
    }
    

    src/floom.php

    <?php
    namespace fknffa;
    
    class floom
    {
    
        public static function sayHello()
        {
            print 'I am in ' . __METHOD__ . PHP_EOL;
        }
    }
    

    执行要求命令

    $ composer require twig/twig
    Using version ^1.23 for twig/twig
    ./composer.json has been updated
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
      - Installing twig/twig (v1.23.1)
    
    Writing lock file
    Generating autoload files
    > fknffa\floom::sayHello
    I am in fknffa\floom::sayHello
    

    【讨论】:

    • 这不起作用。将"scripts": { "pre-install-cmd": [ "php src/notify.php" ], "post-update-cmd": [ "php src/notify.php" ] }, 添加到我的composer.json 文件中,并将一个新的带注释标签推送到packagist.org 并要求该模块。没有对composer require vendor/package-name 执行任何钩子...
    • @Nikolai Tschacher 我更新了我的答案,抱歉迟到了。
    • 澄清一下,需要的包不是根包(因此脚本不会执行)...根包是您从中执行 require cmd 的包. 悲伤的长号
    • 所以安装包的时候没有办法执行脚本?