flyeralarm/php-code-validator
FLYERALARM PHP coding guideline validator: a PSR-12 based PHP_CodeSniffer ruleset with extra standards like lowerCamelCase variables, no Yoda conditions, bans on eval/goto, namespace underscores, and certain class suffixes. Easy Composer embed via ruleset.xml.
composer require --dev flyeralarm/php-code-validator
phpcs.xml in your project root (example below) to reference the ruleset:
<?xml version="1.0"?>
<ruleset name="Laravel Project Rules">
<file>./app/</file>
<file>./tests/</file>
<arg value="sp"/>
<!-- Reference FLYERALARM's ruleset -->
<rule ref="vendor/flyeralarm/php-code-validator/ruleset.xml"/>
<!-- Override or extend rules (optional) -->
<config name="categories" value="PSR12,FLYERALARM"/>
<config name="tab-width" value="4"/>
</ruleset>
vendor/bin/phpcs
--diff to compare against a baseline:
vendor/bin/phpcs --diff=origin/main .
Integrate with Laravel Forge or Git hooks to block non-compliant code:
# Add to `.git/hooks/pre-commit` (or use `husky`/`pre-commit`)
#!/bin/sh
vendor/bin/phpcs --standard=vendor/flyeralarm/php-code-validator/ruleset.xml --colors --report=full .
if [ $? -ne 0 ]; then
echo "❌ Code style violations found. Run 'make sniff' to fix."
exit 1
fi
vendor/bin/phpcs app/Http/Controllers/UserController.php
vendor/bin/phpcs --standard=vendor/flyeralarm/php-code-validator/ruleset.xml --fix .
Settings > Editor > Inspections > PHP.vendor/flyeralarm/php-code-validator/ruleset.xml
name: PHP Code Style Check
on: [push, pull_request]
jobs:
sniff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install --dev
- run: vendor/bin/phpcs --standard=vendor/flyeralarm/php-code-validator/ruleset.xml --report=checkstyle | tee results.xml
- uses: actions/upload-artifact@v3
if: failure()
with:
name: phpcs-results
path: results.xml
--fix.composer.lock) to speed up runs.Extend the ruleset for Laravel-specific needs (e.g., Eloquent query validation):
<!-- In phpcs.xml -->
<rule ref="vendor/flyeralarm/php-code-validator/ruleset.xml"/>
<rule ref="Custom/Laravel/QuerySniff">
<properties>
<property name="allowedMethods" value="where,orderBy,select"/>
</properties>
</rule>
app/CodeSniffer/Custom/Laravel/QuerySniff.php:
<?php
class Custom_Laravel_QuerySniff implements PHP_CodeSniffer_Rules_Sniff {
public function register() {
return array(
T_STRING => $this,
);
}
public function process(Tokens $tokens, $position) {
if ($tokens[$position]['code'] === T_STRING &&
$tokens[$position]['content'] === 'query' &&
$this->hasUnallowedMethod($tokens, $position)) {
return new PHP_CodeSniffer_FixableError(
'Unallowed Eloquent query method detected.',
$position,
$this->correctFix($tokens, $position)
);
}
}
}
Exclude vendor files or specific directories:
<!-- In phpcs.xml -->
<exclude-pattern>./vendor/</exclude-pattern>
<exclude-pattern>./storage/</exclude-pattern>
<exclude-pattern>./tests/Feature/IntegrationTest.php</exclude-pattern>
*RepositoryInterface violates the "no Interface suffix" rule. Workaround:
<rule ref="vendor/flyeralarm/php-code-validator/ruleset.xml">
<exclude name="FLYERALARM.Naming.NoInterfaceSuffix"/>
</rule>
@expectedExceptionMessage for Laravel’s expectExceptionMessage:
// tests/Unit/UserTest.php
public function test_create_user() {
$this->expectException(ValidationException::class);
$this->expectExceptionMessage('The email field is required.');
// ...
}
// app/Console/Commands/CodeSniffCommand.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CodeSniffCommand extends Command {
protected $signature = 'code:sniff {--fix : Auto-fix issues}';
public function handle() {
$command = 'vendor/bin/phpcs';
if ($this->option('fix')) {
$command .= ' --fix';
}
$command .= ' --standard=vendor/flyeralarm/php-code-validator/ruleset.xml .';
shell_exec($command);
}
}
app/Console/Kernel.php:
protected $commands = [
Commands\CodeSniffCommand::class,
];
vendor/bin/phpcs --cache=./phpcs.cache --standard=vendor/flyeralarm/php-code-validator/ruleset.xml .
vendor/bin/phpcs --parallel=4 .
False Positives in Laravel:
RouteServiceProvider uses Route::group(), which may trigger "fully qualified class name" rules.FullyQualifiedSniff:
<rule ref="vendor/flyeralarm/php-code-validator/ruleset.xml">
<exclude name="FLYERALARM.FullyQualified.FullyQualifiedClass"/>
</rule>
use statements at the top of files (Laravel’s convention).Yoda Conditions in Blade:
{{ 1 === $count }} (Yoda), which violates the rule.<file>./resources/views/</file>
<rule ref="vendor/flyeralarm/php-code-validator/ruleset.xml">
<exclude name="FLYERALARM.ControlStructures.YodaCondition"/>
</rule>
Exception Messages:
ValidationException messages may contain dots (e.g., "The email must be valid.").phpcs.xml:
<config name="exception_message_allowed_chars" value=".,!?"/>
PHPStan/Psalm Conflicts:
ReturnTypeSniff (too restrictive). Use PHPStan for type checks instead.composer require --dev phpstan/phpstan
Configure in phpstan.neon:
includes:
- vendor/flyeralarm/php-code-validator/phpstan.neon
Windows Line Endings:
make sniff may fail on Windows due to line endings.dos2unix app/**/*.php tests/**/*.php
vendor/bin/phpcs .
vendor/bin/phpcs -v --standard=vendor/flyeralarm/php-code-validator/ruleset.xml .
How can I help you explore Laravel packages today?