PHP_CodeSniffer
DevOpsツール
PHP_CodeSniffer
概要
PHP_CodeSnifferは、PHPファイルをトークン化し、定義されたコーディング規約の違反を検出するPHP専用の静的コード解析ツールです。PSR-12などの標準規約に準拠したコード品質チェックを実現し、phpcsによる違反検出とphpcbfによる自動修正の2つのツールで構成。PHP、JavaScript、CSSファイルに対応し、GitHub Artifact Attestationsによる署名検証機能も追加。2025年版では新しいPHPCSStandards組織による開発継続とセキュリティ強化により、PHP開発における標準的なコード品質管理ツールとして進化しています。
詳細
PHP_CodeSniffer(ピーエイチピーコードスニファー、PHPCS)は、元々Squiz Labs社によって開発されたPHP用静的コード解析ツールですが、2025年現在はPHPCSStandards組織によってメンテナンスが継続されています。PHP開発において、PSR-12等のコーディング規約準拠を強制し、コード品質の一貫性を保つ業界標準ツールです。
主要な特徴
- 包括的なコード解析: PHP、JavaScript、CSSファイルのトークン化と解析
- PSR標準完全対応: PSR-1、PSR-2、PSR-12等のPHP標準規約準拠
- 二重ツール構成: phpcs(検出)とphpcbf(自動修正)の組み合わせ
- カスタム規約対応: 独自コーディング規約の定義と適用機能
- セキュリティ強化: PHAR署名とGitHub Artifact Attestations検証
- IDE統合: PhpStorm、VS Code等の主要エディター対応
- CI/CD統合: Jenkins、GitHub Actions等での自動品質チェック
- 柔軟な設定: phpcs.xml設定ファイルによる詳細カスタマイズ
- レポート機能: XML、JSON、HTML等の多様な出力形式
2025年版の新機能
- 新組織運営: PHPCSStandards組織による積極的メンテナンス
- 署名検証: GitHub Artifact AttestationsによるPHAR検証機能
- クロスバージョン互換性: PHP Compatibility Coding Standardの統合
- 強化されたレポート: CI/CDパイプライン最適化のXMLサマリーレポート
メリット・デメリット
メリット
- PHP開発での業界標準コーディング規約の自動強制
- PSR-12準拠によるモダンPHPコードの品質保証
- phpcbf自動修正機能による手動修正作業の大幅削減
- 多様なコーディング規約への対応による柔軟性
- IDE統合によるリアルタイムコード品質フィードバック
- CI/CD統合による自動化された品質ゲート実現
- カスタム規約定義による企業・プロジェクト固有要件対応
- 豊富なレポート形式による品質状況の可視化
- セキュリティ強化による信頼性の高いツール配布
- PHP、JavaScript、CSS対応による統一的品質管理
デメリット
- 大規模レガシーコードベースでの大量警告による導入負荷
- 過度な規約強制による開発速度低下のリスク
- カスタム規約作成の複雑さと学習コスト
- 実行時間の長さ(特に大規模プロジェクト)
- 元リポジトリ廃止による混乱と移行作業
- PHP専用のため多言語プロジェクトでの統一ツール使用制限
- 一部自動修正の不完全性(手動確認が必要)
- チーム内でのコーディング規約合意形成の必要性
- 設定ファイルの複雑化によるメンテナンス負荷
- 古いバージョンのPHPサポート制限
参考ページ
- PHP_CodeSniffer 新公式GitHub
- PHP_CodeSniffer 旧リポジトリ
- PSR-12: Extended Coding Style
- PHP Standards Recommendations
- PHP_CodeSniffer Documentation
- Packagist - squizlabs/php_codesniffer
書き方の例
インストールと基本セットアップ
Composer経由でのインストール
# プロジェクトローカルインストール(推奨)
composer require --dev squizlabs/php_codesniffer
# グローバルインストール
composer global require squizlabs/php_codesniffer
# 特定バージョン指定
composer require --dev "squizlabs/php_codesniffer:^3.10"
# インストール確認
./vendor/bin/phpcs --version
./vendor/bin/phpcbf --version
# グローバルインストール確認
phpcs --version
phpcbf --version
PHAR経由でのインストール
# PHARファイルダウンロード
curl -OL https://phars.phpcodesniffer.com/phpcs.phar
curl -OL https://phars.phpcodesniffer.com/phpcbf.phar
# 実行権限付与
chmod +x phpcs.phar phpcbf.phar
# システムPATHに配置
sudo mv phpcs.phar /usr/local/bin/phpcs
sudo mv phpcbf.phar /usr/local/bin/phpcbf
# GitHub Artifact Attestations検証(2025年新機能)
gh attestation verify phpcs.phar --owner PHPCSStandards
# 署名検証
gpg --verify phpcs.phar.asc phpcs.phar
基本的な実行方法
# 基本実行
./vendor/bin/phpcs src/
# 特定ファイルのチェック
./vendor/bin/phpcs src/User.php
# PSR-12標準でのチェック
./vendor/bin/phpcs --standard=PSR12 src/
# 複数標準の組み合わせ
./vendor/bin/phpcs --standard=PSR12,Generic.Files.LineLength src/
# 詳細出力
./vendor/bin/phpcs -v src/
# プログレス表示
./vendor/bin/phpcs -p src/
# 色付き出力
./vendor/bin/phpcs --colors src/
# 特定拡張子のみ
./vendor/bin/phpcs --extensions=php,js src/
# 除外パターン指定
./vendor/bin/phpcs --ignore=*/tests/*,*/vendor/* src/
# レポート形式指定
./vendor/bin/phpcs --report=summary src/
./vendor/bin/phpcs --report=xml src/
./vendor/bin/phpcs --report=json src/
自動修正(phpcbf)
# 基本自動修正
./vendor/bin/phpcbf src/
# 特定標準で修正
./vendor/bin/phpcbf --standard=PSR12 src/
# ドライラン(変更内容確認)
./vendor/bin/phpcbf --dry-run src/
# 詳細出力付き修正
./vendor/bin/phpcbf -v src/
# 特定ファイルのみ修正
./vendor/bin/phpcbf src/Models/User.php
# バックアップ作成付き修正
./vendor/bin/phpcbf --suffix=.bak src/
設定ファイル(phpcs.xml)
<?xml version="1.0"?>
<ruleset name="Custom PHP Standards">
<description>プロジェクト用PHP コーディング規約</description>
<!-- 対象ファイル -->
<file>src</file>
<file>tests</file>
<!-- 除外パターン -->
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*.min.js</exclude-pattern>
<exclude-pattern>*/migrations/*</exclude-pattern>
<!-- PSR-12 基本規約 -->
<rule ref="PSR12">
<!-- 特定ルールの除外 -->
<exclude name="PSR12.Files.FileHeader.SpacingAfterBlock"/>
</rule>
<!-- 追加規約 -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="120"/>
<property name="absoluteLineLimit" value="150"/>
</properties>
</rule>
<rule ref="Generic.Metrics.CyclomaticComplexity">
<properties>
<property name="complexity" value="10"/>
<property name="absoluteComplexity" value="15"/>
</properties>
</rule>
<rule ref="Generic.Metrics.NestingLevel">
<properties>
<property name="nestingLevel" value="5"/>
<property name="absoluteNestingLevel" value="8"/>
</properties>
</rule>
<!-- カスタムルール -->
<rule ref="Squiz.PHP.ForbiddenFunctions">
<properties>
<property name="forbiddenFunctions" type="array">
<element key="eval" value="null"/>
<element key="exec" value="null"/>
<element key="shell_exec" value="null"/>
<element key="var_dump" value="null"/>
<element key="print_r" value="null"/>
</property>
</properties>
</rule>
<!-- 設定オプション -->
<arg name="colors"/>
<arg name="parallel" value="8"/>
<arg value="p"/>
<!-- PHP バージョン設定 -->
<config name="php_version" value="80100"/>
</ruleset>
Laravel プロジェクト用設定
<?xml version="1.0"?>
<ruleset name="Laravel Project Standards">
<description>Laravel プロジェクト用コーディング規約</description>
<!-- Laravel ディレクトリ構造 -->
<file>app</file>
<file>config</file>
<file>database</file>
<file>routes</file>
<file>tests</file>
<!-- Laravel 除外パターン -->
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/storage/*</exclude-pattern>
<exclude-pattern>*/bootstrap/cache/*</exclude-pattern>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/public/hot</exclude-pattern>
<exclude-pattern>*/public/storage</exclude-pattern>
<exclude-pattern>*/.phpstorm.meta.php</exclude-pattern>
<exclude-pattern>*/_ide_helper.php</exclude-pattern>
<!-- PSR-12 + Laravel 固有調整 -->
<rule ref="PSR12"/>
<!-- Laravel Eloquent モデル用調整 -->
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
<exclude-pattern>*/database/migrations/*</exclude-pattern>
<exclude-pattern>*/database/seeders/*</exclude-pattern>
</rule>
<!-- Blade テンプレート用設定 -->
<rule ref="Generic.Files.LineLength">
<exclude-pattern>*.blade.php</exclude-pattern>
</rule>
<!-- Laravel Configuration -->
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>
<rule ref="Generic.PHP.ForbiddenFunctions">
<properties>
<property name="forbiddenFunctions" type="array">
<element key="dd" value="null"/>
<element key="dump" value="null"/>
<element key="var_dump" value="null"/>
</property>
</properties>
<exclude-pattern>*/tests/*</exclude-pattern>
</rule>
</ruleset>
CI/CD統合例
GitHub Actions
# .github/workflows/phpcs.yml
name: PHP CodeSniffer
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: composer
coverage: none
- name: Cache Composer dependencies
uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run PHP CodeSniffer
run: ./vendor/bin/phpcs --standard=PSR12 --report=github src/
- name: Auto-fix with PHP CBF (if push to main)
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: |
./vendor/bin/phpcbf --standard=PSR12 src/
if [ -n "$(git status --porcelain)" ]; then
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add -A
git commit -m "Auto-fix PHP CodeSniffer violations" -a
git push
fi
GitLab CI/CD
# .gitlab-ci.yml
variables:
COMPOSER_CACHE_DIR: ".composer-cache"
cache:
key: composer-cache
paths:
- .composer-cache/
stages:
- quality
phpcs:
stage: quality
image: php:8.2-alpine
before_script:
- apk add --no-cache git
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --prefer-dist --no-progress --no-suggest
script:
- ./vendor/bin/phpcs --standard=PSR12 --report=gitlab src/
- ./vendor/bin/phpcs --standard=PSR12 --report=xml --report-file=phpcs-report.xml src/
artifacts:
reports:
codequality: phpcs-report.xml
paths:
- phpcs-report.xml
expire_in: 1 week
only:
- main
- develop
- merge_requests
IDE統合設定
PhpStorm設定
# PhpStorm設定手順
# File → Settings → PHP → Quality Tools → PHP_CodeSniffer
# Configuration path:
# ローカル: ./vendor/bin/phpcs
# グローバル: /usr/local/bin/phpcs
# Coding standard: PSR12
# または custom: ./phpcs.xml
# 自動実行設定
# File → Settings → Editor → Inspections → PHP → Quality tools
# PHP_CodeSniffer validation をチェック
# External Tools設定
# File → Settings → Tools → External Tools → Add
Name: PHP_CodeSniffer
Description: PHP Code quality checker
Program: $ProjectFileDir$/vendor/bin/phpcs
Arguments: --standard=PSR12 $FilePath$
Working Directory: $ProjectFileDir$
Name: PHP_CBF
Description: PHP Code auto-fixer
Program: $ProjectFileDir$/vendor/bin/phpcbf
Arguments: --standard=PSR12 $FilePath$
Working Directory: $ProjectFileDir$
VS Code設定
// .vscode/settings.json
{
"php.validate.executablePath": "/usr/bin/php",
"phpcs.enable": true,
"phpcs.executablePath": "./vendor/bin/phpcs",
"phpcs.standard": "PSR12",
"phpcbf.enable": true,
"phpcbf.executablePath": "./vendor/bin/phpcbf",
"phpcbf.standard": "PSR12",
"phpcbf.onsave": true,
"[php]": {
"editor.defaultFormatter": "bmewburn.vscode-intelephense-client",
"editor.formatOnSave": true,
"editor.rulers": [120]
},
"files.associations": {
"*.php": "php"
}
}
// tasks.json for VS Code tasks
{
"version": "2.0.0",
"tasks": [
{
"label": "PHP CodeSniffer",
"type": "shell",
"command": "./vendor/bin/phpcs",
"args": ["--standard=PSR12", "src/"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
},
{
"label": "PHP CBF Auto-fix",
"type": "shell",
"command": "./vendor/bin/phpcbf",
"args": ["--standard=PSR12", "src/"],
"group": "build"
}
]
}
カスタムスニフ(独自ルール)作成
<?php
// CustomSniffs/Sniffs/Functions/ForbiddenFunctionsSniff.php
namespace CustomSniffs\Sniffs\Functions;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class ForbiddenFunctionsSniff implements Sniff
{
/**
* 禁止関数一覧
*/
public $forbiddenFunctions = [
'eval',
'exec',
'shell_exec',
'system',
'passthru',
'var_dump',
'print_r',
'debug_print_backtrace',
];
/**
* 監視するトークン
*/
public function register()
{
return [T_STRING];
}
/**
* トークン処理
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$functionName = $tokens[$stackPtr]['content'];
if (!in_array($functionName, $this->forbiddenFunctions)) {
return;
}
// 関数呼び出しかチェック
$nextToken = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
if ($tokens[$nextToken]['code'] !== T_OPEN_PARENTHESIS) {
return;
}
$error = 'Forbidden function "%s" found. Use alternative approach.';
$data = [$functionName];
$phpcsFile->addError($error, $stackPtr, 'Found', $data);
}
}
<!-- カスタムスニフ読み込み設定 -->
<?xml version="1.0"?>
<ruleset name="Custom Standards">
<description>独自コーディング規約</description>
<!-- カスタムスニフディレクトリ -->
<config name="installed_paths" value="./CustomSniffs"/>
<!-- 基本規約 -->
<rule ref="PSR12"/>
<!-- カスタムルール -->
<rule ref="CustomSniffs.Functions.ForbiddenFunctions">
<properties>
<property name="forbiddenFunctions" type="array">
<element key="eval" value="危険な関数です"/>
<element key="var_dump" value="デバッグ関数です"/>
</property>
</properties>
</rule>
</ruleset>
高度な使用例とトラブルシューティング
# パフォーマンス最適化
./vendor/bin/phpcs --parallel=8 src/
# 特定エラーのみ表示
./vendor/bin/phpcs --severity=error src/
# 警告レベル以上のみ
./vendor/bin/phpcs --warning-severity=0 src/
# キャッシュ使用
./vendor/bin/phpcs --cache=.phpcs-cache src/
# デバッグ出力
./vendor/bin/phpcs -vvv src/User.php
# インストール済み標準確認
./vendor/bin/phpcs -i
# 特定ルールの詳細確認
./vendor/bin/phpcs --explain src/User.php
# 統計情報出力
./vendor/bin/phpcs --report=info src/
# git hooks統合
# .git/hooks/pre-commit
#!/bin/bash
FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep '\.php$')
if [ -n "$FILES" ]; then
./vendor/bin/phpcs --standard=PSR12 $FILES
if [ $? -ne 0 ]; then
echo "PHP CodeSniffer found violations. Please fix and try again."
exit 1
fi
fi
# Makefile統合
.PHONY: phpcs phpcbf quality
phpcs:
./vendor/bin/phpcs --standard=PSR12 src/ tests/
phpcbf:
./vendor/bin/phpcbf --standard=PSR12 src/ tests/
quality: phpcs
@echo "Code quality check completed"