ongr/ongr-strict-standard
A strict PHP_CodeSniffer coding standard from ONGR that enforces clean, consistent, high-quality PHP code. Built on PSR standards with additional rules for formatting, naming, and code structure, it helps teams catch style issues early and keep codebases readable and maintainable.
This is a PHPCS ruleset package, not a library — it ships an XML standard (based on Squiz + PSR-2) and nothing else. "Using" it means pointing PHP_CodeSniffer at it.
Install as a dev dependency, pinned to a PHPCS-2-compatible toolchain and an explicit standard version.
composer require --dev ongr/ongr-strict-standard:^2.1
The ruleset dates from 2015 and was written against squizlabs/php_codesniffer 2.x; the 2.1.x line is maintenance patches to that same XML, not a port. If your project already has PHPCS 3/4, isolate the linter in a Composer bin dir (bamarni/composer-bin-plugin) rather than fighting version resolution in the root composer.json.
Look first at vendor/ongr/ongr-strict-standard/ruleset.xml. That single file is the package. Read it before configuring anything: it tells you which Squiz sniffs are enabled, which PSR-2 rules are tightened, and what the registered standard name is (confirm with vendor/bin/phpcs -i — it is typically ONGR). On 2.1.2 specifically, look for the doc-comment alignment exception added in #117 — it changes which alignment violations still fire.
Reference it by file path, not by name. This sidesteps the whole installed_paths problem (see Gotchas). Create a project phpcs.xml:
<?xml version="1.0"?>
<ruleset name="MyProject">
<description>Project standard: ONGR strict + local overrides</description>
<file>src</file>
<file>tests</file>
<arg name="extensions" value="php"/>
<arg value="p"/> <!-- show progress -->
<arg value="s"/> <!-- show sniff codes: essential -->
<rule ref="vendor/ongr/ongr-strict-standard/ruleset.xml"/>
</ruleset>
First real use case: audit, don't enforce. Run it once against a representative directory and read the source report before wiring it into CI:
vendor/bin/phpcs --report=source src/
vendor/bin/phpcs --report=summary src/
The source report ranks sniffs by violation count. That output is your decision document for which rules you keep, exclude, or defer — you will almost certainly exclude a few. Do this again after any ruleset bump: counts shift between patch releases.
Composer scripts as the entry point. Keep the raw phpcs invocation out of muscle memory so everyone runs the same thing:
"scripts": {
"lint": "phpcs",
"lint:fix": "phpcbf",
"lint:diff": "phpcs $(git diff --name-only --diff-filter=ACM origin/main... | grep '\\.php$' | tr '\\n' ' ')"
}
With phpcs.xml in the root, bare phpcs/phpcbf picks up files, extensions, and the ruleset automatically.
Treat ruleset bumps as a baseline change, not a no-op. The package has no code to test, so a patch release can only alter which violations you get. After upgrading (e.g. to 2.1.2), re-run --report=source and diff against your previous numbers, then reconcile your <exclude> list — entries that existed only to silence alignment noise may now be dead weight, and under PHPCS 3.x an unused phpcs:ignore is itself an error.
Layered ruleset — base standard, per-path relaxations. Override inside the <rule ref> block so exclusions apply only where you intend:
<rule ref="vendor/ongr/ongr-strict-standard/ruleset.xml">
<!-- relax docblock strictness in tests -->
<exclude name="Squiz.Commenting.FunctionComment.MissingParamTag"/>
<exclude name="Squiz.Commenting.FunctionComment.MissingReturn"/>
</rule>
<rule ref="vendor/ongr/ongr-strict-standard/ruleset.xml">
<exclude-pattern>src/Migrations/*</exclude-pattern>
</rule>
Exclusion names must be the complete sniff code (Standard.Category.Sniff.Code) — a typo fails silently. Get them from phpcs -s or --report=source, not from memory of the old ruleset.
Legacy-code rollout: diff-only enforcement. Don't try to clean a 2015-era codebase in one PR. Gate the CI job on changed files (see lint:diff above) and let the standard ratchet forward. Pair it with a pre-commit hook using the same script so developers see failures locally, not in CI.
CI reporting. Two reports, one run each: humans read full, machines read checkstyle/json.
vendor/bin/phpcs --report=full --report-checkstyle=build/phpcs.xml
Exit code is non-zero on errors — that's your gate. Warnings don't fail by default; if you want them to, add <arg name="warning-severity" value="1"/> or --warning-severity=1.
IDE integration. In PhpStorm, enable the PHP CodeSniffer validation inspection, set the interpreter to your project PHP, the tool path to vendor/bin/phpcs, and the coding standard to the absolute path of vendor/ongr/ongr-strict-standard/ruleset.xml. Do not rely on PhpStorm "discovering" the ONGR standard by name — it uses the same global installed_paths config that bites you on the CLI.
GrumPHP / task runners. Wire the phpcs task with standard: vendor/ongr/ongr-strict-standard/ruleset.xml and ignore_patterns: [vendor/*]. Same path-based rule as everywhere else.
Two-pass fixing. Always phpcbf first, then phpcs. Squiz sniffs auto-fix a lot of whitespace/alignment; docblock content and naming violations are not fixable and will remain — running phpcs first just wastes a pass.
^2.1) so an unexpected tag can't shift your lint baseline mid-sprint.ERROR: Referenced sniff "..." does not exist, or worse, are silently dropped so your "strict" standard quietly enforces less. Always pin the PHPCS version the ruleset was written for, and sanity-check with -s that expected sniffs actually fire — especially after a ruleset bump, since a sniff that stops firing looks identical to a codebase that got cleaner.<exclude name="...Alignment..."> entries, --warning-severity tweaks, or phpcs:ignore comments you added purely to silence alignment are now redundant — and unused ignores are errors under PHPCS 3.x. Diff your excludes against vendor/ongr/ongr-strict-standard/ruleset.xml after upgrading.--standard=ONGR fails with "coding standard ONGR is not installed." PHPCS resolves names via installed_paths, which is a global per-machine config (phpcs --config-set installed_paths ...) — a classic "works on my machine." Referencing vendor/ongr/ongr-strict-standard/ruleset.xml by path is portable; prefer it, and never commit reliance on --config-set.// @codingStandardsIgnoreLine and // @codingStandardsIgnoreFile in 2.x vs // phpcs:ignore / // phpcs:disable in 3.x. Mixing them means your suppressions either don't apply or trigger "unused ignore" errors depending on the runtime.Squiz.Commenting.FunctionComment demands @param/@return/@throws with types and descriptions for every method. On a legacy codebase this is typically 60–80% of all violations. Decide early whether you exclude these codes or suppress them per-file; do not let them drown out real issues in the CI log. The #117 alignment exception trims a sliver of this — it does not make the standard docblock-friendly.phpcbf cannot fix: missing docblocks, wrong tag order, naming conventions, or line length. If your fix loop isn't converging, check the residual phpcs report before assuming a tool bug — and re-check it after a ruleset upgrade, where new/removed violations can masquerade as non-convergence..inc, .phtml, .module files are ignored unless you pass --extensions. Similarly, <file> entries in phpcs.xml are the only thing scanned when a ruleset is present — passing explicit paths on the CLI overrides them, which is why the diff-only script works.--cache). Full-repo runs are slow and re-tokenize every file. Scope to directories, use --report=summary while iterating, and reserve full --report=full for CI artifacts.<exclude>/<exclude-pattern>, tightened via inline <rule ref="..."> properties (<property name="lineLimit" value="120"/>), or extended with custom sniffs registered through installed_paths. Because upgrades only ever touch that one XML file, keep your phpcs.xml and the vendor copy diffable.slevomat/coding-standard on PSR-12 plus friendsofphp/php-cs-fixer for the auto-fixable whitespace/alignment layer — both actively maintained and PHP-8-aware. Migrating means mapping your ONGR <exclude> list to Slevomat sniff codes; keep the old ruleset.xml in tools/ as the reference diff.How can I help you explore Laravel packages today?