Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Yii2 Coding Standards Laravel Package

yiisoft/yii2-coding-standards

The PHP_CodeSniffer coding standard used by Yii2 core and official extensions. Based on PSR-12 with documented Yii-specific exceptions, it lets you check and automatically fix PHP code with phpcs and phpcbf via the Yii2 ruleset. Requires PHP 7.4+ and PHP_CodeSniffer 4.0.2+.

View on GitHub
Deep Wiki
Context7

Getting Started

This is not a Laravel package — there is no service provider, no config to publish, no config/ merge. It is a PHP_CodeSniffer standard (a directory of sniffs plus a ruleset.xml) that happens to describe Yii2 conventions, built on top of PSR-12 since 3.0.0. Day-to-day value for a Laravel developer comes from three concrete situations:

  1. You maintain/are migrating a legacy Yii2 app next to a Laravel app and want one phpcs toolchain.
  2. You need Yii2-specific sniffs (array syntax, docblock/annotation formats, naming) as a reference or base for your own custom ruleset.
  3. You're doing a Yii2 → Laravel migration and want to lint the old half of the monorepo without a second tooling stack.

Install (dev only):

composer require --dev yiisoft/yii2-coding-standards
composer require --dev dealerdirect/phpcodesniffer-composer-installer

The second package is the important one — it registers PHPCS "installed paths" automatically. On Composer ≥ 2.2 you must approve the plugin:

composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true

Look here first, in this order:

Where Why
vendor/yiisoft/yii2-coding-standards/Yii2/ruleset.xml The actual standard name (Yii2) and every <rule>/<exclude> it applies. This is the real docs.
vendor/yiisoft/yii2-coding-standards/Yii2/Sniffs/ Yii2-only sniffs — the part you can't get from vanilla PSR-12.
README.md Install + CLI invocation; it is thin, don't expect more.
Release 3.0.0 notes The PSR-12 migration — the single most consequential change if you inherit a 2.x config.

First use case — prove it runs before wiring anything:

vendor/bin/phpcs -i                                  # 'Yii2' must appear in the list
vendor/bin/phpcs --standard=Yii2 --extensions=php app/legacy-yii/
vendor/bin/phpcs -e --standard=Yii2                  # enumerate every sniff the standard enables

If Yii2 is not in phpcs -i, the installed-path registration failed — stop and fix that before writing any XML.

Implementation Patterns

Dedicated ruleset file, scoped by directory

Do not run this standard across a whole Laravel app. Scope it. A single .phpcs.xml.dist at repo root with per-directory <rule> blocks is the cleanest pattern for a hybrid repo:

<?xml version="1.0"?>
<ruleset name="Hybrid">
    <description>Yii2 legacy + Laravel</description>

    <file>app</file>
    <file>legacy</file>
    <arg name="extensions" value="php"/>
    <arg name="parallel" value="8"/>
    <arg name="cache" value=".phpcs.cache"/>

    <!-- Only the legacy Yii2 subtree gets Yii2 rules -->
    <rule ref="Yii2">
        <include-pattern>legacy/*</include-pattern>
    </rule>

    <!-- Laravel side: PSR-12 only -->
    <rule ref="PSR12">
        <include-pattern>app/*</include-pattern>
    </rule>

    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/node_modules/*</exclude-pattern>
    <exclude-pattern>*/storage/*</exclude-pattern>
    <exclude-pattern>*.blade.php</exclude-pattern>
</ruleset>

<include-pattern> inside a <rule> is the key trick — it lets you keep one config and one CI step while applying two different standards.

Two-file split: legacy vs. new

A common refinement once the legacy tree is "frozen":

  • .phpcs-legacy.xml → ref="Yii2", run in CI as non-blocking (report only).
  • .phpcs.xml.dist → ref="PSR12" (+ your own sniffs), run as blocking.

Wire both into composer.json:

"scripts": {
    "lint":        "phpcs",
    "lint:legacy": "phpcs --standard=.phpcs-legacy.xml --report=summary",
    "lint:fix":    "phpcbf --standard=.phpcs-legacy.xml legacy/"
}

--report=summary for the legacy run keeps CI noise to one line per file instead of thousands of violation rows.

Autofix, but only where it's safe

phpcbf against the Yii2 standard will rewrite whitespace, array syntax, and docblock layout. On Laravel code that is destructive (it will touch things Pint owns). The safe pattern:

vendor/bin/phpcbf --standard=Yii2 legacy/           # Yii2 subtree only, one commit, then review
vendor/bin/pint app/                                # Laravel side stays with Pint

Never point both phpcbf and pint at the same directory — see Gotchas.

CI gate

- name: Install
  run: composer install --no-interaction --prefer-dist

- name: PHPCS (blocking, Laravel side)
  run: vendor/bin/phpcs --standard=PSR12 --report=checkstyle --report-file=phpcs.xml app/

- name: PHPCS (informational, Yii2 legacy)
  run: vendor/bin/phpcs --standard=.phpcs-legacy.xml --report=summary legacy/ || true

|| true is deliberate during migration — you want the violation count visible in the log, not a red build on day one.

IDE integration

PhpStorm: Settings → PHP → Quality Tools → PHP_CodeSniffer, set the interpreter and the phpcs path, then Settings → Editor → Inspections → PHP → PHP CodeSniffer validation and pick Yii2 as the coding standard. This is the highest-leverage step for a team — violations show up inline before a commit, not in CI after review. Note the README's PhpStorm advice (Set from... → PSR12) applies to the formatter, not the linter; the linter's standard is still Yii2.

Custom sniffs extending Yii2's

The package ships sniff/token-parsing classes built for Yii2 syntax. If you're writing house rules, extending them beats extending AbstractSniffUnitTest from scratch — you inherit the correct token handling for Yii2 idioms. Register your sniffs in your own standard directory and reference it; don't patch into vendor/.

Migration sequencing that actually works

  1. Run phpcs --standard=Yii2 --report=source legacy/ — get a sniff-level histogram, not a file-level one.
  2. Disable the top-3 noisiest sniffs globally in your ruleset (usually comment/docblock and array-formatting rules that PSR-12 disagrees on).
  3. phpcbf once, review the diff, commit it as a single "style baseline" commit — this makes git blame recoverable.
  4. Flip CI from || true to blocking on the legacy tree only after violation count drops under a threshold you chose in step 1.

Gotchas and Tips

The standard is named Yii2, not yiisoft. A lot of blog posts and even internal specs reference <rule ref="yiisoft"/>. That will fail with "Referenced sniff 'yiisoft' does not exist." Verify with vendor/bin/phpcs -i before trusting any snippet.

Installed paths are the #1 setup failure. Without dealerdirect/phpcodesniffer-composer-installer (or a manual --runtime-set installed_paths vendor/yiisoft/yii2-coding-standards), Yii2 won't resolve even though the package is installed. The plugin itself silently does nothing until you approve it in allow-plugins — Composer 2.2+ will prompt, CI will not. Pin it in composer.json explicitly.

PSR-12 baseline means heavy overlap with Laravel's own tooling. Since 3.0.0 the ruleset is PSR-12-derived. That means the Yii2 standard will duplicate most of what laravel/pint (which wraps PHP-CS-Fixer) already formats. Running both produces conflicting auto-fixes and merge churn. Pick one formatter per directory; use PHPCS as the linter only.

Upgrading 2.x → 3.x is a breaking style change, not a patch. 2.x was PSR-2-based; 3.x is PSR-12. Pin ^3.0 and treat the upgrade as a separate formatting commit across the legacy tree. Same applies to 3.0.1, which specifically excludes a PSR12.Files.FileHeader.SpacingAfterBlock false positive — if you're on 3.0.0 and seeing spurious file-header errors, that's why.

Exclude Blade and anything non-.php. PHPCS's default --extensions can surprise you; set <arg name="extensions" value="php"/> explicitly and add <exclude-pattern>*.blade.php</exclude-pattern>. Yii2 sniffs have no concept of Blade directives and will emit nonsense.

Expect Yii2-idiom false positives on Laravel code. Static facade calls (Route::get(), Cache::put()), container-resolved $request injection, and Laravel's Arr::/Str:: helpers can trip Yii2 naming/static-call sniffs. Don't try to make Laravel code pass the Yii2 standard — that's the wrong direction. Scope the standard to the legacy tree (<include-pattern>), full stop.

Disable sniffs surgically, not the whole standard. When a rule is genuinely wrong for your context:

<rule ref="Yii2">
    <exclude name="Yii2.Commenting.FunctionComment"/>
    <exclude name="PSR12.Files.FileHeader"/>
</rule>

Use phpcs -s to get the sniff code in the violation output — you need the exact Standard.Category.SniffName to exclude it, and the default output only gives you the message.

Debugging toolkit:

vendor/bin/phpcs -s --standard=Yii2 file.php        # show sniff codes alongside messages
vendor/bin/phpcs --report=source --standard=Yii2 .  # which sniffs fire most, across the codebase
vendor/bin/phpcs --report=diff --standard=Yii2 .    # what phpcbf would change, without changing it
vendor/bin/phpcs -e --standard=Yii2                 # everything enabled
vendor/bin/phpcs --severity=5 --standard=Yii2 .     # only the nasty stuff

The --report=source histogram is the single most useful debugging command here — it tells you whether your ruleset is badly configured or your codebase is just messy.

Warnings vs. errors. PHPCS distinguishes them; CI fails on both by default. For a gradual rollout:

vendor/bin/phpcs --warning-severity=0 --standard=Yii2 legacy/

That lets style warnings pass while still blocking genuine errors.

Performance. PHPCS is a token-streaming parser and is slow on large trees. Always set <arg name="parallel" value="8"/> and <arg name="cache" value=".phpcs.cache"/>, and gitignore the cache file (.phpcs.cache) so it doesn't get committed or leak across CI runs in a stale state.

No Laravel-side extension points exist. There's no config/coding-standards.php, no facade, no publishable config. Everything is .phpcs.xml XML plus sniff classes. If someone on the team expects "install and it just works," reset that expectation early — this is a ruleset, and rulesets are configured, not bootstrapped.

Maintenance posture. Last release is 3.0.1 and the package is maintained by the Yii core team for Yii's own repo. It is not tracking Laravel or PHP 8.x language features. Pin the exact version in composer.lock, and if you find yourself heavily excluding sniffs, that's a signal to fork the ruleset internally rather than accumulate a 200-line exclusion list.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo