PHP 8.6 arrives on November 19. DressCode already rewrites code for it. 16 days Upgrading to a newer PHP →

From Nette Coding Standard to DressCode

Nette Coding Standard, the nette/coding-standard package with its ecs command, is no longer developed, and version 3 is the last one. Its standard lives on in DressCode, built in under the name nette. Moving a project, ncs.php and ncs.xml included, takes a few lines of configuration, and the only surprise is the first fix, which reformats more files than you expect.

What Has Changed

Nette Coding Standard was a thin wrapper around PHP CS Fixer and PHP_CodeSniffer with a bundle of rules from Slevomat: two tools, two configurations (ncs.php for the fixer, ncs.xml for the sniffer) and the ecs command that ran it all.

In DressCode, the standard is a preset. It is called nette and is part of DressCode, so every project has it available, whether it uses Nette or not. It is based on PER Coding Style, which it adjusts to the layout of the Nette libraries (tabs, two blank lines between methods and more), and it also uses the sets cleanup, types and correctness, turning off a few of their decisions; exactly what it contains is shown in the overview of standards and sets. Nothing else is needed:

  • no package besides DressCode itself; nette/coding-standard stays at version 3 and you remove it from your project;
  • no command besides dresscode; ecs is not used anymore.

Installation and Configuration

composer require --dev dresscode/dresscode

Keep in mind that DressCode requires PHP 8.4 to 8.6, and because it is a development dependency, your project must run on one of these versions too. The PHP version the tool runs on and the version your code is written for are two different numbers, though: DressCode reads the target version from the composer.json of the project, see Installation. If your project runs on an older PHP, install DressCode globally instead.

Put a dresscode.neon into the root of the project, with the standard and the extra sets you want:

use:
	- nette
	- compilerOptimizations   # optional

nameResolution: certain

# optional: native types wherever PHP reads them
types:
	declaration:
		parameter: required
		property: required
		return: required

paths:
	- src
	- tests

Version 3 skipped the directories expected, tmp and fixtures* automatically. DressCode skips tmp too; add the others to excludePaths if your project has them, for example excludePaths: [tests/**/expected, tests/**/fixtures*].

Some fixes rely on a function being global, including what the compilerOptimizations set does. DressCode makes them without your permission only when it knows what is in your namespaces. That is why the configuration says nameResolution: certain, and if you really have some functions or constants in namespaces, you also list them in the namespaces key; without that, such fixes are only reported. The page Functions and Constants in Namespaces explains why.

Then you check and fix with DressCode itself:

dresscode check
dresscode fix

A setting that differs from version 3 only in its value is written as a decision. A project that wants one blank line between methods instead of two, and does not want === everywhere there is ==, adds:

blankLines:
	aroundMethods: 1

expressions:
	comparison:
		loose: keep

Converting the Configuration

There is no command that converts ncs.php and ncs.xml, but they are usually a few lines long, so you carry them over by hand. To find the decision that replaces a fixer or a sniff of version 3, search for its name in dresscode catalogue:

dresscode catalogue | grep strict_comparison

It prints the decision, what it is about, and the names of the rules of other tools it covers: expressions.comparison.loose A loose comparison, ... (covers strict_comparison, SlevomatCodingStandard.Operators.DisallowEqualOperators).

version 3 DressCode
ncs.php with 'fixer' => false the decision the fixer covers, with the value keep
ncs.xml with <rule ref="$presets/optimize-fn.xml"/> the compilerOptimizations set in the use key
ncs.xml with <exclude-pattern> the excludePaths key
ncs.xml with <exclude-pattern> inside <rule> an override in the overrides key that gives the decision keep for those paths
--config-file overrides.php dresscode.neon in the root of the project
--preset php81, --preset php nothing; DressCode takes the target PHP version from your composer.json

Then replace ecs check and ecs fix with dresscode check and dresscode fix in your CI, Git hooks and editor, uninstall nette/coding-standard, and delete ncs.php and ncs.xml.

The First Fix Reformats More Than You Expect

DressCode is not the same as version 3 line by line, and that is on purpose. Some differences fix what version 3 left alone: a capital letter at the start of a comment // Comment, a /* enum */ comment before case, declare(strict_types=1) on the line of the opening tag, a non-breaking space written literally in a string. Across the Nette packages, this came to more than a hundred files out of almost three thousand.

Make it a separate commit: dresscode fix, a commit with no other changes, done. Going through it line by line is not worth it; what is worth it is knowing that the commit contains nothing else.

What Has Stayed

  • The phpcs:ignore comments with the names of PHP_CodeSniffer and Slevomat sniffs keep working; dresscode migrate suppressions rewrites them to dresscode:ignore.
  • Custom sniffs and fixers, if there were any, are rewritten following the guide; a rewritten sniff is usually several times shorter.

Show on GitHub · Report a problem with this page on GitHub · Nov 2, 2026