Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .php-cs-fixer-rules.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
],
'modernize_types_casting' => true,
'mb_str_functions' => true,
'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'],
'no_alias_functions' => true,
'no_binary_string' => true,
'no_empty_comment' => true,
Comment on lines 44 to 50
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header docblock in this rules file still references “PER projects” and an old vendor path (interaction-design-foundation/php-cs-fixer-rules.php). Since this file is being touched and is now effectively a supported integration point, update the header usage example/text to match the current package name/path (and/or point users to IxDFCodingStandard\PhpCsFixer\Config / Rules::get()).

Copilot uses AI. Check for mistakes.
Expand All @@ -69,7 +70,9 @@
'no_whitespace_before_comma_in_array' => true,
'normalize_index_brace' => true,
'nullable_type_declaration' => ['syntax' => 'question_mark'],
'nullable_type_declaration_for_default_null_value' => true,
'object_operator_without_whitespace' => true,
'ordered_imports' => ['imports_order' => ['class', 'function', 'const']],
/*
* @see https://github.com/slevomat/coding-standard/issues/1620#issuecomment-1758006718
* 'ordered_class_elements' => [
Expand Down
53 changes: 53 additions & 0 deletions IxDFCodingStandard/PhpCsFixer/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php declare(strict_types=1);

namespace IxDFCodingStandard\PhpCsFixer;

use PhpCsFixer\Config as BaseConfig;
use PhpCsFixer\Finder;
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;

/**
* Pre-configured PHP-CS-Fixer config factory for IxDF projects.
* @see README.md for usage examples
*/
final class Config
{
// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
/** @param array<string, array<string, mixed>|bool> $ruleOverrides Rules to merge on top of the shared ruleset */
public static function create(string $projectDir, array $ruleOverrides = [], ?Finder $finder = null): BaseConfig
{
$finder ??= self::defaultFinder($projectDir);

return (new BaseConfig())
->setParallelConfig(ParallelConfigFactory::detect())
->setUsingCache(true)
->setCacheFile($projectDir.'/.cache/.php-cs-fixer.cache')
->setRiskyAllowed(true)
->setIndent(' ')
->setLineEnding("\n")
->setRules(array_merge(Rules::get(), $ruleOverrides))
->setFinder($finder);
Comment on lines +15 to +29
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test coverage is introduced for this new public factory API. Adding PHPUnit tests that assert the returned config has the expected rules applied (including override precedence), sets a Finder, and uses the expected cache/parallel settings would help prevent accidental breaking changes.

Copilot uses AI. Check for mistakes.
}

private static function defaultFinder(string $projectDir): Finder
{
return Finder::create()
->in($projectDir)
->exclude([
'.cache',
'.docker',
'bootstrap/cache',
'node_modules',
'public',
'storage',
'vendor',
])
->name('*.php')
->notName('*.blade.php')
->notName('_ide_helper.php')
->notName('.phpstorm.meta.php')
->ignoreDotFiles(false)
->ignoreVCS(true)
->ignoreVCSIgnored(true);
}
}
21 changes: 21 additions & 0 deletions IxDFCodingStandard/PhpCsFixer/Rules.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php declare(strict_types=1);

namespace IxDFCodingStandard\PhpCsFixer;

/**
* Shared PHP-CS-Fixer rules for IxDF projects.
* @see https://mlocati.github.io/php-cs-fixer-configurator/
*/
final class Rules
{
// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
/** @var array<string, array<string, mixed>|bool>|null */
private static ?array $rules = null;

// phpcs:ignore SlevomatCodingStandard.TypeHints.DisallowMixedTypeHint.DisallowedMixedTypeHint
/** @return array<string, array<string, mixed>|bool> */
public static function get(): array
{
Comment on lines +14 to +18
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No test coverage is introduced for this new public rules accessor. Consider adding a small PHPUnit test asserting Rules::get() returns an array and is stable across calls (e.g., same content), so changes to the rules file path/loading don’t silently break consumers.

Copilot uses AI. Check for mistakes.
return self::$rules ??= require dirname(__DIR__, 2).'/.php-cs-fixer-rules.php';
}
}
115 changes: 54 additions & 61 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,107 +3,100 @@
[![PHP Psalm Level](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard/level.svg)](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard)
[![PHP Psalm Type Coverage](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard/coverage.svg)](https://shepherd.dev/github/InteractionDesignFoundation/coding-standard)

# IxDF Coding Standard for Laravel
# IxDF Coding Standard

An opinionated ruleset focused on strict types.
Suitable for both applications and packages.
An opinionated coding standard for PHP/Laravel projects. Provides two independent tools — use either one or both together:

- **PHP_CodeSniffer** — custom sniffs for strict types and Laravel conventions
- **PHP-CS-Fixer** — shared config with 80+ rules based on PER-CS 3.0

## Installation

1. Install the package via composer by running:
```shell
composer require --dev interaction-design-foundation/coding-standard
```

2. Add composer scripts into your `composer.json`:
```json
"scripts": {
"cs:check": "phpcs -p -s --colors --report-full --report-summary",
"cs:fix": "phpcbf -p --colors"
}
```
## PHP_CodeSniffer

3. Create file `phpcs.xml` on the base path of your repository with content
Create `phpcs.xml` in your project root:
```xml
<?xml version="1.0"?>
<ruleset name="My Coding Standard">
<!-- Include all rules from the IxDF Coding Standard -->
<rule ref="IxDFCodingStandard"/>

<!-- Paths to check -->
<file>app</file>
<file>config</file>
<file>database</file>
<file>lang</file>
<file>routes</file>
<file>tests</file>
</ruleset>
```

## Usage
## PHP-CS-Fixer

- To run checks only:
Create `.php-cs-fixer.php` in your project root:

```shell
composer cs:check
```
```php
<?php declare(strict_types=1);

- To automatically fix many CS issues:
use IxDFCodingStandard\PhpCsFixer\Config;

```shell
composer cs:fix
return Config::create(__DIR__);
```

## Ignoring parts of a File

Disable parts of a file:
With rule overrides:

```php
$xmlPackage = new XMLPackage;
// phpcs:disable
$xmlPackage['error_code'] = get_default_error_code_value();
$xmlPackage->send();
// phpcs:enable
return Config::create(__DIR__, ruleOverrides: [
'final_public_method_for_abstract_class' => false,
]);
```

Disable a specific rule:
With a custom Finder:

```php
// phpcs:disable Generic.Commenting.Todo.Found
$xmlPackage = new XMLPackage;
$xmlPackage['error_code'] = get_default_error_code_value();
// TODO: Add an error message here.
$xmlPackage->send();
// phpcs:enable
```
use IxDFCodingStandard\PhpCsFixer\Config;
use PhpCsFixer\Finder;

Ignore a specific violation:
$finder = Finder::create()->in(__DIR__)->name('*.php');

return Config::create(__DIR__, finder: $finder);
```

If you only need the rules array:
```php
$xmlPackage = new XMLPackage;
$xmlPackage['error_code'] = get_default_error_code_value();
// phpcs:ignore Generic.Commenting.Todo.Found
// TODO: Add an error message here.
$xmlPackage->send();
$rules = \IxDFCodingStandard\PhpCsFixer\Rules::get();
```

## Development
## Usage

```shell
vendor/bin/phpcs # check with PHP_CodeSniffer
vendor/bin/phpcbf # fix with PHP_CodeSniffer
vendor/bin/php-cs-fixer fix --dry-run --diff # check with PHP-CS-Fixer
vendor/bin/php-cs-fixer fix # fix with PHP-CS-Fixer
```

### Versioning
> **New rules or Sniffs may not be introduced in minor or bugfix releases and should always be based on the develop
branch and queued for the next major release, unless considered a bugfix for existing rules.**
### Composer scripts (recommended)

Add to your `composer.json`:

## Reference
```json
"scripts": {
"cs": "@cs:fix",
"cs:check": ["@php-cs-fixer:dry", "@phpcs"],
"cs:fix": ["@php-cs-fixer", "@phpcbf"],
"phpcs": "phpcs -p -s --colors --report-full --report-summary",
"phpcbf": "phpcbf -p --colors",
"php-cs-fixer": "php-cs-fixer fix --no-interaction --ansi --quiet",
"php-cs-fixer:dry": "php-cs-fixer fix --no-interaction --ansi --verbose --dry-run"
}
```

Rules can be added, excluded or tweaked locally, depending on your preferences.
More information on how to do this can be found here:
Then run:

- [Coding Standard Tutorial](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial)
- [Configuration Options](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options)
- [Selectively Applying Rules](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset#selectively-applying-rules)
- [Customisable Sniff Properties](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Customisable-Sniff-Properties)
- Other coding standards (inspiring us):
- [Slevomat coding standard](https://github.com/slevomat/coding-standard)
- [Doctrine coding standard](https://github.com/doctrine/coding-standard)
- [Laminas coding standard](https://github.com/laminas/laminas-coding-standard)
```shell
composer cs:check # run both tools in check mode
composer cs:fix # run both tools in fix mode
composer phpcs # PHP_CodeSniffer only
composer php-cs-fixer # PHP-CS-Fixer only
```
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"name": "interaction-design-foundation/coding-standard",
"description": "IxDF Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"description": "IxDF coding standard: PHP_CodeSniffer rules and shared PHP-CS-Fixer configuration.",
"license": "MIT",
"type": "phpcodesniffer-standard",
"require": {
"php": "^8.3",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"friendsofphp/php-cs-fixer": "^3.89",
"slevomat/coding-standard": "^8.25",
"squizlabs/php_codesniffer": "^4.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.89",
"phpunit/phpunit": "^12.4",
"vimeo/psalm": "^6.13"
},
Expand Down