PHP项目Composer脚本钩子

wen PHP项目 4

本文目录导读:

PHP项目Composer脚本钩子

  1. 脚本钩子类型
  2. 执行时机
  3. 实际应用示例
  4. 脚本中的特殊命令
  5. 最佳实践
  6. 调试脚本
  7. 注意事项

在PHP项目中,Composer的脚本钩子(Script Hooks)是一个非常强大的功能,它允许你在Composer执行特定操作时自动运行自定义脚本,以下是详细的指南:

脚本钩子类型

安装/更新相关钩子

{
    "scripts": {
        "pre-install-cmd": "Your\\Class\\Method",
        "post-install-cmd": "Your\\Class\\Method",
        "pre-update-cmd": "Your\\Class\\Method",
        "post-update-cmd": "Your\\Class\\Method",
        "pre-install-package": "Your\\Class\\Method",
        "post-install-package": "Your\\Class\\Method",
        "pre-update-package": "Your\\Class\\Method",
        "post-update-package": "Your\\Class\\Method",
        "pre-package-install": "Your\\Class\\Method",
        "post-package-install": "Your\\Class\\Method"
    }
}

包管理钩子

{
    "scripts": {
        "pre-autoload-dump": "Your\\Class\\Method",
        "post-autoload-dump": "Your\\Class\\Method",
        "post-root-package-install": "Your\\Class\\Method",
        "post-create-project-cmd": "Your\\Class\\Method",
        "pre-archive-cmd": "Your\\Class\\Method",
        "post-archive-cmd": "Your\\Class\\Method"
    }
}

自定义脚本

{
    "scripts": {
        "dev-server": "php -S localhost:8000 -t public",
        "test": "phpunit",
        "lint": "phpcs --standard=PSR2 src/",
        "fix": "phpcbf --standard=PSR2 src/"
    }
}

执行时机

钩子名称 触发时机
pre-install-cmd composer install 执行前
post-install-cmd composer install 执行后
pre-update-cmd composer update 执行前
post-update-cmd composer update 执行后
pre-autoload-dump 生成自动加载文件前
post-autoload-dump 生成自动加载文件后
pre-package-install 安装包之前(每个包触发)
post-package-install 安装包之后(每个包触发)
pre-package-update 更新包之前(每个包触发)
post-package-update 更新包之后(每个包触发)

实际应用示例

基础用法

{
    "scripts": {
        "post-install-cmd": [
            "php artisan migrate",
            "php artisan cache:clear"
        ],
        "post-update-cmd": [
            "@php artisan optimize",
            "@php artisan config:cache"
        ]
    }
}

使用PHP类方法

创建自定义脚本类:

<?php
// src/Composer/Scripts.php
namespace App\Composer;
class Scripts
{
    public static function postInstall()
    {
        // 设置目录权限
        $dirs = ['storage', 'bootstrap/cache'];
        foreach ($dirs as $dir) {
            if (!file_exists($dir)) {
                mkdir($dir, 0755, true);
            }
            chmod($dir, 0755);
        }
        // 创建.env文件
        if (!file_exists('.env')) {
            copy('.env.example', '.env');
            echo ".env file created\n";
        }
        // 执行特定命令
        self::runCommand('php artisan key:generate');
        self::runCommand('php artisan migrate --seed');
    }
    public static function postUpdate()
    {
        // 清理缓存
        self::runCommand('php artisan cache:clear');
        self::runCommand('php artisan config:clear');
        self::runCommand('php artisan view:clear');
    }
    private static function runCommand($command)
    {
        echo "Running: $command\n";
        passthru($command);
    }
}

在composer.json中引用:

{
    "scripts": {
        "post-install-cmd": [
            "App\\Composer\\Scripts::postInstall"
        ],
        "post-update-cmd": [
            "App\\Composer\\Scripts::postUpdate"
        ]
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

条件执行脚本

{
    "scripts": {
        "post-update-cmd": [
            "@php -r \"if (file_exists('artisan')) { passthru('php artisan migrate --force'); }\"",
            "@if [ -f artisan ]; then php artisan optimize; fi"
        ]
    }
}

执行其他Composer命令

{
    "scripts": {
        "full-install": [
            "@composer install --no-dev",
            "@composer dump-autoload --optimize",
            "@composer run-script post-install"
        ]
    }
}

环境特定脚本

{
    "scripts": {
        "post-install-cmd": [
            "@php -r \"if (getenv('APP_ENV') === 'production') { passthru('php artisan config:cache'); }\"",
            "@php artisan storage:link"
        ]
    }
}

脚本中的特殊命令

{
    "scripts": {
        "test": [
            "@phpunit",  // 执行phpunit命令
            "@php -l src/",  // 执行PHP命令
            "@composer validate",  // 执行composer命令
            "@php -r \"echo 'Hello World';\""  // 执行PHP代码
        ],
        "dev": [
            "@composer run-script setup-db",
            "@php -S localhost:8000"
        ]
    }
}

最佳实践

安全的脚本配置

{
    "scripts": {
        "post-install-cmd": [
            "@php artisan config:cache || true",  // 失败继续
            "@php artisan route:cache || true"
        ],
        "post-update-cmd": [
            "@php artisan migrate --force || exit 1"  // 失败停止
        ]
    },
    "scripts-descriptions": {
        "post-install-cmd": "Post install commands",
        "test": "Run PHPUnit tests"
    }
}

避免常见错误

  • 不要在钩子中执行交互式命令
  • 确保脚本在Windows和Linux下都可执行
  • 使用@php前缀代替直接的php命令
  • 考虑脚本的执行时间
  • 添加错误处理

使用事件机制

{
    "scripts": {
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ],
        "post-autoload-dump": [
            "@php artisan package:discover --ansi"
        ]
    }
}

脚本分组

{
    "scripts": {
        "setup": [
            "@php artisan migrate",
            "@php artisan db:seed",
            "@php artisan key:generate"
        ],
        "setup:dev": [
            "@composer run-script setup",
            "@php artisan serve"
        ],
        "setup:prod": [
            "@php artisan migrate --force",
            "@php artisan config:cache",
            "@php artisan route:cache"
        ]
    }
}

调试脚本

# 查看所有可用的脚本
composer list
# 运行特定脚本
composer run-script post-install-cmd
# 显示脚本执行的详细输出
composer run-script test --verbose
# 跳过脚本执行
composer install --no-scripts
composer update --no-scripts
# 只执行特定脚本
composer run-script --help

注意事项

  1. 版本兼容性:确保Composer版本支持所有使用的钩子
  2. 执行顺序:多个脚本按数组顺序执行
  3. 错误处理:一个脚本失败可能中断后续执行
  4. 性能考虑:避免在钩子中执行耗时操作
  5. 安全风险:hook可以执行任意命令,确保composer.json不被篡改

通过合理使用Composer脚本钩子,可以自动化项目开发中的重复性任务,提高开发效率。

抱歉,评论功能暂时关闭!