diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 71b90ce..ddf2ad3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,10 +1,12 @@ { "name": "PHP", "image": "mcr.microsoft.com/devcontainers/php:1-8.3", - "forwardPorts": ["8000","9000"], - "containerEnv": { - "NODE_ENV": "development" - }, + "forwardPorts": [ + 8000 + ], + "containerEnv": { + "NODE_ENV": "development" + }, "customizations": { "vscode": { "settings": {}, @@ -19,6 +21,5 @@ "onAutoForward": "notify" } }, - "postAttachCommand": "php -S 0.0.0.0:8000" -} +} \ No newline at end of file diff --git a/.gitea/dependabot.yaml b/.gitea/dependabot.yaml deleted file mode 100644 index 1f79a6f..0000000 --- a/.gitea/dependabot.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# For more details, see https://containers.dev/guide/dependabot -version: 2 -updates: - - package-ecosystem: "devcontainers" - directory: "/" - schedule: - interval: weekly \ No newline at end of file diff --git a/.gitea/workflows/code-check.yaml b/.gitea/workflows/code-check.yaml new file mode 100644 index 0000000..fd22581 --- /dev/null +++ b/.gitea/workflows/code-check.yaml @@ -0,0 +1,97 @@ +name: PHP Code Check + +on: + push: + branches: [ main, master, develop ] + pull_request: + branches: [ main, master, develop ] + +jobs: + code-quality: + name: Code Quality Check + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: mbstring, xml, ctype, json + coverage: none + tools: php-cs-fixer, phpstan, psalm + + - name: Validate PHP syntax + run: | + echo "Checking PHP syntax..." + find . -name "*.php" -not -path "./vendor/*" -exec php -l {} \; | grep -v "No syntax errors" + if [ $? -eq 0 ]; then + echo "✓ All PHP files have valid syntax" + fi + + - name: Install Composer dependencies + if: hashFiles('composer.json') != '' + run: | + if [ -f "composer.json" ]; then + composer install --prefer-dist --no-progress --no-suggest + else + echo "No composer.json found, skipping..." + fi + + - name: Run PHP_CodeSniffer + continue-on-error: true + run: | + if [ -f "composer.json" ]; then + if composer show --installed | grep -q "squizlabs/php_codesniffer"; then + vendor/bin/phpcs --standard=PSR12 --colors -p . + else + echo "PHP_CodeSniffer not installed, skipping..." + fi + else + echo "No composer.json, skipping PHP_CodeSniffer..." + fi + + - name: Run PHP CS Fixer (dry-run) + continue-on-error: true + run: | + if command -v php-cs-fixer &> /dev/null; then + php-cs-fixer fix --dry-run --diff --verbose + else + echo "PHP CS Fixer not available, skipping..." + fi + + - name: Run PHPStan + continue-on-error: true + run: | + if [ -f "composer.json" ]; then + if composer show --installed | grep -q "phpstan/phpstan"; then + vendor/bin/phpstan analyse --level=5 --no-progress . + elif command -v phpstan &> /dev/null; then + phpstan analyse --level=5 --no-progress . + else + echo "PHPStan not installed, skipping..." + fi + else + echo "No composer.json, skipping PHPStan..." + fi + + - name: Run Psalm + continue-on-error: true + run: | + if [ -f "composer.json" ]; then + if composer show --installed | grep -q "vimeo/psalm"; then + vendor/bin/psalm --no-progress + elif command -v psalm &> /dev/null; then + psalm --no-progress + else + echo "Psalm not installed, skipping..." + fi + else + echo "No composer.json, skipping Psalm..." + fi + + - name: Check code formatting + run: | + echo "✓ Code quality checks completed" diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..81b5a7c --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,34 @@ +in(__DIR__) + ->exclude('vendor') + ->exclude('node_modules') + ->name('*.php') + ->ignoreDotFiles(true) + ->ignoreVCS(true); + +$config = new PhpCsFixer\Config(); +return $config + ->setRules([ + '@PSR12' => true, + 'array_syntax' => ['syntax' => 'short'], + 'ordered_imports' => ['sort_algorithm' => 'alpha'], + 'no_unused_imports' => true, + 'not_operator_with_successor_space' => false, + 'trailing_comma_in_multiline' => true, + 'phpdoc_scalar' => true, + 'unary_operator_spaces' => true, + 'binary_operator_spaces' => true, + 'blank_line_before_statement' => [ + 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], + ], + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_var_without_name' => true, + 'single_trait_insert_per_statement' => true, + ]) + ->setFinder($finder); diff --git a/README.md b/README.md index 0322001..c60c1b7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,71 @@ # php -Php 项目工程模板 +Php 项目工程模板(带自动代码校验) ## 使用方法 -``` +启动开发服务器: +```bash php -S 0.0.0.0:8000 ``` +## 代码质量检查 + +### 安装依赖 + +```bash +composer install +``` + +### 运行代码检查 + +运行所有检查: +```bash +composer check +``` + +单独运行检查: +```bash +# PHP 语法检查 +composer syntax-check + +# 代码风格检查 +composer cs-check + +# 代码风格自动修复 +composer cs-fix + +# 静态分析 (PHPStan) +composer phpstan + +# 静态分析 (Psalm) +composer psalm + +# 自动格式化代码 +composer fix +``` + +## 自动化工作流 + +项目包含自动化代码校验工作流 (`.gitea/workflows/code-check.yml`),会在以下情况自动运行: + +- 推送代码到 `main`, `master`, 或 `develop` 分支 +- 创建 Pull Request + +工作流会自动执行: +1. PHP 语法验证 +2. 代码风格检查 (PSR-12 标准) +3. 静态代码分析 (PHPStan & Psalm) +4. 代码格式检查 + +## 配置文件说明 + +- `.php-cs-fixer.php` - PHP CS Fixer 代码格式配置 +- `phpcs.xml` - PHP_CodeSniffer 代码风格配置 +- `phpstan.neon` - PHPStan 静态分析配置 +- `psalm.xml` - Psalm 静态分析配置 +- `composer.json` - 项目依赖和脚本配置 + ### 版权说明 Copyright @ Mengning Software diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..061dad7 --- /dev/null +++ b/composer.json @@ -0,0 +1,35 @@ +{ + "name": "template/php-project", + "description": "PHP project template with automated code quality checks", + "type": "project", + "license": "MIT", + "require": { + "php": ">=7.4" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.7", + "phpstan/phpstan": "^1.10", + "vimeo/psalm": "^5.0", + "friendsofphp/php-cs-fixer": "^3.0" + }, + "scripts": { + "check": [ + "@syntax-check", + "@cs-check", + "@phpstan", + "@psalm" + ], + "syntax-check": "find . -name '*.php' -not -path './vendor/*' -exec php -l {} \\;", + "cs-check": "phpcs", + "cs-fix": "phpcbf", + "phpstan": "phpstan analyse --no-progress", + "psalm": "psalm --no-progress", + "fix": "php-cs-fixer fix" + }, + "config": { + "sort-packages": true, + "allow-plugins": { + "php-http/discovery": true + } + } +} \ No newline at end of file diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..731a059 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,31 @@ + + + PHP CodeSniffer configuration for the project + + + . + + + */vendor/* + */node_modules/* + *.js + *.css + + + + + + + + + + + + + + + + + + + diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..0a919a5 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,11 @@ +parameters: + level: 5 + paths: + - . + excludePaths: + - vendor + - node_modules + ignoreErrors: + # Add specific errors to ignore here if needed + checkMissingIterableValueType: false + checkGenericClassInNonGenericObjectType: false diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..f199e3c --- /dev/null +++ b/psalm.xml @@ -0,0 +1,16 @@ + + + + + + + + + +