szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset
Hybrid PHP_CodeSniffer ruleset for OOP WordPress: PSR-12 Extended formatting plus Neutron/WPCS checks, strict types, file permissions, docblocks, and selected Slevomat rules. Install via Composer and run phpcs with PSR12NeutronRuleset.
composer require --dev szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset
vendor/):
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --ignore=vendor/ app/
# .github/workflows/phpcs.yml
name: PHPCS
on: [push, pull_request]
jobs:
phpcs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: ./vendor/bin/phpcs --standard=PSR12NeutronRuleset --error-severity=5 --warning-severity=0 app/
WordPress.DB.DirectDatabaseQuery).WordPress.Security).TypeHint, Arrays) to avoid developer pushback.phpcs via a hook (e.g., husky) to catch issues before commits:
# .husky/pre-commit
#!/bin/sh
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --warning-severity=3 app/
// .php-cs-fixer.dist.php (optional for IDE integration)
return (new PhpCsFixer\Config())
->setRules([
'@PSR12NeutronRuleset' => true,
]);
- name: PHPCS (Laravel + WordPress Hybrid)
run: |
./vendor/bin/phpcs \
--standard=PSR12NeutronRuleset \
--ignore=vendor/,tests/ \
--exclude=WordPress.DB.DirectDatabaseQuery,WordPress.VIP \
--error-severity=5 \
app/
./vendor/bin/phpcs --standard=PSR12NeutronRuleset app/Http/ app/Models/ | tee phpcs-results.txt
ruleset.xml in your project root:
<?xml version="1.0"?>
<ruleset name="LaravelHybridRuleset">
<rule ref="PSR12NeutronRuleset">
<!-- Disable WordPress-specific rules for Laravel -->
<exclude name="WordPress.DB.DirectDatabaseQuery"/>
<exclude name="WordPress.Security.EscapeOutput.OutputNotEscaped"/>
<!-- Adjust Slevomat strictness -->
<arg name="severity" value="5" name="SlevomatCodingStandard.TypeHint"/>
</rule>
<!-- Add custom sniffs for Laravel patterns -->
<rule ref="Custom/Laravel/NoMagicMethodOverrides"/>
</ruleset>
./vendor/bin/phpcs --standard=LaravelHybridRuleset app/
Route::, Cache::) as "disallowed short open tags":
<exclude name="WordPress.Security.NonceVerification.Missing"/>
WordPress.DB rules entirely if using Eloquent:
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --exclude=WordPress.DB.* app/
NoUnusedPrivateMethods if Laravel’s magic methods (e.g., __get) trigger false positives:
<exclude name="SlevomatCodingStandard.UnusedPrivateElements.UnusedPrivateMethod"/>
--fix for PSR-12 formatting (but avoid for Neutron/Slevomat):
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --fix app/ --rules=PSR12
False Positives with Laravel Patterns:
WordPress.Security rules may flag Laravel’s {{ }} Blade syntax or Facades.<exclude name="WordPress.Security.EscapeOutput.OutputNotEscaped"/>
Performance Overhead:
--cache.php-parallel-lint.tests/ and vendor/ directories.Slevomat Over-Strictness:
TypeHint or NoUnusedPrivateMethods may break Laravel’s dynamic properties or magic methods.<arg name="severity" value="3" name="SlevomatCodingStandard.TypeHint"/>
Neutron’s WordPress-Centric Rules:
WordPress.DB.DirectDatabaseQuery are irrelevant for Laravel but may still trigger warnings.WordPress.DB category:
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --exclude=WordPress.DB.* app/
IDE Misconfiguration:
.php-cs-fixer.dist.php or PHPCS plugins../vendor/bin/phpcs --standard=PSR12NeutronRuleset app/Http/Controllers/UserController.php
--verbose to see which rules are being applied:
./vendor/bin/phpcs --standard=PSR12NeutronRuleset --verbose app/
@package Tag Confusion:
@package tags using PEAR-style naming (e.g., Vendor\Package), which may conflict with Composer autoloading.<exclude name="Generic.Files.DocCommentPackageNotMatchClass"/>
File Permissions:
644), which may conflict with Laravel’s storage/ or bootstrap/cache/ directories../vendor/bin/phpcs --standard=PSR12NeutronRuleset --ignore=storage/,bootstrap/cache/ app/
Strict Types:
TypeHint rule may fail on Laravel’s dynamic properties (e.g., $fillable in models).@var annotations:
/** @var array<string, mixed> */
protected $fillable = [];
// Custom/Laravel/NoMagicMethodOverrides.php
class NoMagicMethodOverrides extends AbstractSniff {
public function register() {
return [
T_METHOD => $this,
];
}
public function process(Tokens $tokens, $position) {
// Logic to detect magic method overrides (e.g.,
How can I help you explore Laravel packages today?