本文目录导读:

我来提供一个完整的 PHP 项目 Git 预提交钩子(pre-commit hook)方案。
基础 PHP 语法检查钩子
#!/bin/bash
# .git/hooks/pre-commit
echo "🔍 运行 PHP 预提交检查..."
# 获取暂存区中的 PHP 文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep '\.php$')
if [ -z "$STAGED_FILES" ]; then
echo "✓ 没有 PHP 文件需要检查"
exit 0
fi
# 1. PHP 语法检查
echo "📝 检查 PHP 语法..."
ERRORS=0
for FILE in $STAGED_FILES; do
if [ -f "$FILE" ]; then
OUTPUT=$(php -l "$FILE" 2>&1)
if [ $? -ne 0 ]; then
echo "❌ 语法错误: $FILE"
echo "$OUTPUT"
ERRORS=$((ERRORS + 1))
fi
fi
done
if [ $ERRORS -gt 0 ]; then
echo "❌ 发现 $ERRORS 个语法错误,提交已阻止"
exit 1
fi
echo "✓ 所有 PHP 文件语法正确"
exit 0
带有代码风格检查的完整钩子
#!/bin/bash
# .git/hooks/pre-commit - 完整版
echo "🚀 开始 PHP 预提交检查..."
# 设置颜色
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 获取暂存区中的 PHP 文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep '\.php$')
if [ -z "$STAGED_FILES" ]; then
echo -e "${GREEN}✓ 没有 PHP 文件需要检查${NC}"
exit 0
fi
ERRORS=0
WARNINGS=0
echo "📁 待检查的文件:"
echo "$STAGED_FILES" | sed 's/^/ - /'
# 1. PHP 语法检查
echo -e "\n${YELLOW}[1/3] PHP 语法检查${NC}"
for FILE in $STAGED_FILES; do
if [ -f "$FILE" ]; then
OUTPUT=$(php -l "$FILE" 2>&1)
if [ $? -ne 0 ]; then
echo -e "${RED}❌ $FILE: ${NC}$OUTPUT"
ERRORS=$((ERRORS + 1))
else
echo -e "${GREEN}✓ $FILE${NC}"
fi
else
echo -e "${YELLOW}⚠ 文件不存在: $FILE${NC}"
fi
done
# 2. PHP CS Fixer 风格检查(如果安装了)
echo -e "\n${YELLOW}[2/3] 代码风格检查 (PHP CS Fixer)${NC}"
if command -v php-cs-fixer &> /dev/null; then
for FILE in $STAGED_FILES; do
if [ -f "$FILE" ]; then
# 检查模式而非自动修复
OUTPUT=$(php-cs-fixer fix "$FILE" --dry-run --diff 2>&1)
if [ $? -ne 0 ]; then
echo -e "${YELLOW}⚠ 风格问题: $FILE${NC}"
echo "$OUTPUT" | tail -5
WARNINGS=$((WARNINGS + 1))
else
echo -e "${GREEN}✓ $FILE 风格正确${NC}"
fi
fi
done
else
echo -e "${YELLOW}⚠ php-cs-fixer 未安装,跳过风格检查${NC}"
fi
# 3. PHPStan 静态分析(可选)
echo -e "\n${YELLOW}[3/3] PHPStan 静态分析${NC}"
if [ -f "vendor/bin/phpstan" ]; then
# 只分析暂存的文件
PHPSTAN_OUTPUT=$(vendor/bin/phpstan analyse $STAGED_FILES --no-progress 2>&1)
if [ $? -ne 0 ]; then
echo -e "${RED}$PHPSTAN_OUTPUT${NC}"
ERRORS=$((ERRORS + 1))
else
echo -e "${GREEN}✓ PHPStan 分析通过${NC}"
fi
else
echo -e "${YELLOW}⚠ PHPStan 未安装,跳过静态分析${NC}"
fi
# 最终结果
echo -e "\n${YELLOW}📊 检查结果总结:${NC}"
if [ $ERRORS -gt 0 ]; then
echo -e "${RED}❌ $ERRORS 个错误${NC}"
echo -e "${YELLOW}⚠ $WARNINGS 个警告${NC}"
echo -e "${RED}🚫 提交被阻止,请先修复错误${NC}"
exit 1
else
echo -e "${GREEN}✓ 没有错误,$WARNINGS 个警告${NC}"
echo -e "${GREEN}✅ 可以提交${NC}"
exit 0
fi
安装脚本
#!/bin/bash
# install-hooks.sh - 安装钩子脚本
echo "📦 正在安装 Git 预提交钩子..."
# 复制钩子文件
cp pre-commit .git/hooks/pre-commit
# 设置执行权限
chmod +x .git/hooks/pre-commit
# 确保 PHP 相关工具已安装
echo "🔍 检查 PHP 工具..."
if ! command -v php &> /dev/null; then
echo "❌ PHP 未安装"
exit 1
else
echo "✓ PHP $(php --version | head -n 1)"
fi
# 可选工具检查
if ! command -v composer &> /dev/null; then
echo "⚠ Composer 未安装"
else
echo "✓ Composer 已安装"
fi
echo "✅ 钩子安装完成!"
echo "您现在可以尝试提交代码来测试钩子"
配置文件 (.php-cs-fixer.php)
<?php
// .php-cs-fixer.php
$finder = PhpCsFixer\Finder::create()
->in(__DIR__)
->exclude('vendor')
->exclude('storage')
->exclude('node_modules')
->name('*.php')
->notName('*.blade.php')
->ignoreDotFiles(true)
->ignoreVCS(true);
return (new PhpCsFixer\Config())
->setRules([
'@PSR12' => true,
'array_syntax' => ['syntax' => 'short'],
'no_unused_imports' => true,
'ordered_imports' => ['sort_algorithm' => 'alpha'],
'single_quote' => true,
'trailing_comma_in_multiline' => true,
'phpdoc_align' => true,
'blank_line_before_statement' => true,
'no_extra_blank_lines' => true,
'return_type_declaration' => ['space_before' => 'none'],
'no_whitespace_before_comma_in_array' => true,
'whitespace_after_comma_in_array' => true,
'concat_space' => ['spacing' => 'one'],
'cast_spaces' => true,
'lowercase_cast' => true,
'magic_constant_casing' => true,
'native_function_casing' => true,
'function_typehint_space' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'class_attributes_separation' => ['elements' => ['method' => 'one']],
])
->setFinder($finder);
高级版本(支持多个校验工具)
#!/bin/bash
# .git/hooks/pre-commit - 高级版本
set -e
echo "🔍 开始全面的 PHP 代码检查..."
# 获取暂存的文件
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep '\.php$')
ERRORS=0
# 检查函数
check_syntax() {
local file=$1
if ! php -l "$file" 2>&1; then
echo "❌ 语法错误: $file"
return 1
fi
return 0
}
check_code_sniffer() {
local file=$1
if [ -f "vendor/bin/phpcs" ]; then
if ! vendor/bin/phpcs "$file" --standard=PSR2 2>&1; then
echo "❌ PSR2 规范违规: $file"
return 1
fi
else
echo "⚠ PHPCS 未安装,跳过"
fi
return 0
}
# 主检查流程
for FILE in $STAGED_FILES; do
echo "检查: $FILE"
# 1. 语法检查
check_syntax "$FILE" || ERRORS=$((ERRORS + 1))
# 2. 代码规范检查
check_code_sniffer "$FILE" || ERRORS=$((ERRORS + 1))
# 3. 安全检查(可选)
if [ -f "vendor/bin/phpstan" ]; then
vendor/bin/phpstan analyse "$FILE" || ERRORS=$((ERRORS + 1))
fi
done
if [ $ERRORS -gt 0 ]; then
echo "❌ 发现 $ERRORS 个问题,禁止提交"
exit 1
fi
echo "✅ 所有检查通过,可以提交!"
安装到项目
# 1. 创建钩子目录 mkdir -p .git/hooks # 2. 下载或创建钩子脚本 cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash # ... 脚本内容 ... EOF # 3. 设置权限 chmod +x .git/hooks/pre-commit # 4. 可选:提交钩子到仓库 # 创建 hooks 目录并保存脚本 mkdir -p .githooks # 然后把钩子脚本放到该目录 # 配置 Git 使用该目录 git config core.hooksPath .githooks
使用说明
-
临时跳过钩子(不推荐):
git commit --no-verify -m "提交信息"
-
查看钩子状态:
ls -la .git/hooks/pre-commit
-
测试钩子:
# 故意创建一个语法错误 echo "<?php echo 'test';" >> test.php git add test.php git commit -m "测试钩子"
这个预提交钩子将帮助你:
- ✅ 验证 PHP 语法
- ✅ 检查代码风格规范
- ✅ 运行静态分析
- ✅ 防止提交错误代码
- ✅ 保持代码质量一致性
请根据项目需求选择适当的钩子版本。