umanit/coding-standard
Umanit's PHP coding standard package ships a ready-to-use PHP-CS-Fixer configuration and custom fixers, so Laravel and PHP projects can enforce consistent code style across teams with one Composer dependency and almost no setup.
Install as a dev dependency so it never ships to production:
composer require --dev umanit/coding-standard
Inspect what you actually installed before writing any config. The composer package name and the PHP_CodeSniffer standard name are usually different:
ls vendor/umanit/coding-standard
cat vendor/umanit/coding-standard/composer.json
# find the ruleset and note its name attribute
grep -R "<ruleset" vendor/umanit/coding-standard --include="*.xml"
Look first at: the README.md, the composer.json (which PHPCS version it constrains), and the ruleset.xml (the name="..." value is what you pass to --standard=).
Create a phpcs.xml.dist at the project root. This becomes the single entry point for CLI, CI, and IDEs:
<?xml version="1.0"?>
<ruleset name="Project">
<description>Project coding standard</description>
<file>src</file>
<file>tests</file>
<arg name="extensions" value="php"/>
<arg name="colors"/>
<arg value="sp"/> <!-- progress + show sniff codes -->
<!-- Replace with the name from the vendor ruleset -->
<rule ref="UmanIT"/>
</ruleset>
Run it on a single directory first — do not start with the whole repo:
vendor/bin/phpcs --standard=phpcs.xml.dist src/
vendor/bin/phpcbf --standard=phpcs.xml.dist src/ # safe auto-fixes
First use case: pick one small, actively maintained directory (e.g. a new feature folder), get it fully green, and only then expand scope. This gives you a working CI gate in an afternoon without a 2,000-error cleanup project.
Composer scripts as the team interface. Nobody should memorize flags; expose two commands and document them:
{
"scripts": {
"cs": "phpcs",
"cs:fix": "phpcbf",
"cs:changed": "phpcs --filter=GitModified"
}
}
CI integration. Run composer cs as its own job, not glued to tests, so failures are unambiguous. Use a machine-readable report for your platform:
vendor/bin/phpcs --report=checkstyle --report-file=build/phpcs.xml
# or for humans in CI logs
vendor/bin/phpcs --report=full --report=source
--report=source is the best onboarding tool: it aggregates by sniff, so you see "this rule fired 312 times" instead of 312 line items. Use it to decide what to exclude first.
Editor wiring. Point PHPStorm's CodeSniffer inspection at vendor/bin/phpcs with the project phpcs.xml.dist; in VS Code, the phpcs extension with phpcs.standard set to the same file. This is where the package earns its keep day-to-day — feedback before commit.
Pre-commit on staged files only. Full-repo lint is too slow for a hook. Either use GrumPHP/captainhook, or a small shell step that maps git diff --cached --name-only --diff-filter=ACM into phpcs arguments. Keep auto-fix out of the hook unless the team agrees, since it can stage surprising changes.
Layering, not forking. Extend the vendor standard in your own ruleset instead of copying it:
<rule ref="UmanIT">
<exclude name="UmanIT.Some.Sniff"/>
</rule>
<!-- per-path relaxations -->
<rule ref="Generic.Files.LineLength">
<properties>
<property name="lineLimit" value="120"/>
</properties>
</rule>
Legacy directory strategy. Rather than phpcs:ignore sprinkled everywhere, scope the ruleset to new code and add <exclude-pattern> entries for legacy paths. Ratchet: move one directory into the <file> list each sprint.
Speed. Use --cache (add .phpcs.cache to .gitignore) and --parallel=$(nproc) in local scripts. On repos over a few thousand files this is the difference between 4s and 60s.
composer.json, read the diff before every bump, and accept that you may need to fork it. Do not let it become a blocking dependency for a release.umanit/coding-standard is the composer package; PHPCS wants the name attribute from the ruleset XML (UmanIT or similar). If you get "Referenced sniff ... does not exist", you passed the wrong identifier. Confirm with vendor/bin/phpcs -i — installed standards are listed there.squizlabs/php_codesniffer (^3.x). If another dev tool wants PHPCS 4, Composer will refuse. Resolve by aligning tools, not by --ignore-platform-reqs. Run composer why squizlabs/php_codesniffer before blaming the new package.phpcbf only fixes sniffs that declare themselves fixable. Always run a clean git status before phpcbf, then re-run phpcs — fixers can reveal new violations and occasionally conflict in ordering across overlapping sniffs.vendor/, var/, storage/, node_modules/, generated proxies, and often migrations. These produce noise that trains the team to ignore the tool.exclude, or drop the fixer. Never run both fixers in the same hook.--warning-severity=0, and tighten later.<exclude-pattern> list. Prefer the explicit list — it is a visible ratchet rather than a hidden suppression file.phpcs run create a false sense of quality.<rule ref="YourStandard.Sniffs.YourSniff"/> plus an autoload entry in your own package — useful when the vendor standard lags behind your conventions.How can I help you explore Laravel packages today?