hosmelq/php-coding-standard

Opinionated ECS, Rector, and PHPStan presets for PHP and Laravel packages and applications.
81
Install
composer require hosmelq/php-coding-standard
Latest Version:v1.1.0
PHP:^8.4
License:MIT
Last Updated:Oct 20, 2026
Links: GitHub  ·  Packagist
Maintainer: hosmelq

PHP Coding Standard

Opinionated ECS, Rector, and PHPStan presets for PHP and Laravel packages and applications, with custom fixers that lay out code by line width.

Requirements

  • PHP 8.4+

Installation

Allow the PHPStan extension installer, then install PHP Coding Standard with Composer:

composer config allow-plugins.phpstan/extension-installer true
composer require --dev hosmelq/php-coding-standard

The package includes every tool and extension the presets use, except Larastan. Laravel packages and applications require it themselves:

composer require --dev larastan/larastan

Choose a preset

Use the same row in every tool:

Project ECS Rector PHPStan
PHP package or application ECS_PHP RECTOR_PHP phpstan-php.neon
Laravel package ECS_LARAVEL_PACKAGE RECTOR_LARAVEL_PACKAGE phpstan-laravel-package.neon
Laravel application ECS_LARAVEL_APP RECTOR_LARAVEL_APP phpstan-laravel-app.neon

ECS and Rector presets are constants on HosmelQ\PhpCodingStandard\CodingStandard. PHPStan presets are files in the package's config directory. Each Laravel preset builds on the one above it. Larastan boots Laravel packages with Orchestra Testbench, which they already require for their tests.

Configure the tools

Create ecs.php:

<?php

declare(strict_types=1);

use HosmelQ\PhpCodingStandard\CodingStandard;
use Symplify\EasyCodingStandard\Config\ECSConfig;

return ECSConfig::configure()
    ->withSets([CodingStandard::ECS_PHP])
    ->withPaths([__DIR__.'/src', __DIR__.'/tests']);

Create rector.php. To apply Pest's coding style rules with Pest 5, require pestphp/pest-plugin-rector and add CodingStandard::RECTOR_PEST:

composer require --dev pestphp/pest-plugin-rector
<?php

declare(strict_types=1);

use HosmelQ\PhpCodingStandard\CodingStandard;
use Rector\Config\RectorConfig;

return RectorConfig::configure()
    ->withSets([CodingStandard::RECTOR_PHP, CodingStandard::RECTOR_PEST])
    ->withPaths([__DIR__.'/src', __DIR__.'/tests']);

Create phpstan.neon:

includes:
  - vendor/hosmelq/php-coding-standard/config/phpstan-php.neon

parameters:
  paths:
    - src

Run the tools:

vendor/bin/rector process
vendor/bin/ecs check --fix
vendor/bin/phpstan analyse

Run Rector before ECS so ECS lays out Rector's changes. One ECS run is enough. PHPStan runs at level max with strict, deprecation, safe function, disallowed call, and full type coverage rules. The Laravel application preset also analyses app, bootstrap, config, database, and routes. PHPStan caches its results in .cache/phpstan, so add .cache to .gitignore.

Lay out code

The ECS presets keep code within 100 columns. Chains that fit join onto one line, and long lines break their outermost construct first:

$invoice = Invoice::factory()
    ->for($customer)
    ->createOne();

$response = $this->actingAs($user)->post(route('invoices.store'), ['number' => 'INV-001', 'currency' => 'USD', 'paid' => true]);

if ($subscription->status === SubscriptionStatus::PastDue && $user->canManageBilling($organization)) {

Becomes:

$invoice = Invoice::factory()->for($customer)->createOne();
$response = $this->actingAs($user)->post(route('invoices.store'), [
    'number' => 'INV-001',
    'currency' => 'USD',
    'paid' => true,
]);

if (
    $subscription->status === SubscriptionStatus::PastDue
    && $user->canManageBilling($organization)
) {
  • Long method chains with three or more calls put each call on its own line.
  • Arguments, parameters, and arrays put each item on its own line with a trailing comma. A call's last associative array, or its only array, opens inside the call.
  • Long conditions break before &&, ||, ??, ., ?, and :.
  • Long arrow functions move their body to the next line, starting with =>.
  • Lists with // comments between items put each item on its own line.
  • Test calls such as it('title', function () {}) keep their title and closure on one line.
  • Blank lines between consecutive variable assignments are removed.

Strings, comments, comparisons, and long test titles can stay longer than the line length.

Change the line length

Configure LineLengthFixer in ecs.php. The line length must be at least 80:

use HosmelQ\PhpCodingStandard\Fixer\LineLengthFixer;

return ECSConfig::configure()
    ->withSets([CodingStandard::ECS_PHP])
    ->withConfiguredRule(LineLengthFixer::class, ['line_length' => 120]);

Customize presets

Call withConfiguredRule(), withRules(), or withSkip() after withSets() in ECS and Rector:

use PhpCsFixer\Fixer\Strict\StrictParamFixer;

return ECSConfig::configure()
    ->withSets([CodingStandard::ECS_PHP])
    ->withSkip([StrictParamFixer::class]);

In PHPStan, project parameters override the preset and lists are merged. Add ! after a key, such as paths!, to replace a list.

Review risky changes

Some rules change behavior, such as DeclareStrictTypesFixer, MbStrFunctionsFixer, StrictComparisonFixer, and StrictParamFixer, and the Laravel presets convert dates to Carbon. Review these changes, or skip a rule with withSkip().

Add runtime dependencies

The package is a development dependency. If your code calls Safe\ functions or uses Carbon, require thecodingmachine/safe or nesbot/carbon directly.

Development

Run the test suite with:

composer test

Changelog

See CHANGELOG.md for a list of changes.

Contributing

Pull requests are welcome. Please run the test suite before submitting changes.

License

The MIT License (MIT). Please see License File for more information.

Related Packages

laravel/pao

Agent-optimized output for PHP testing tools

21,393,471 725
ugarit/pao

Agent-optimized output for PHP testing tools

349 0
svnjn/php-standards

Shared strict coding standards, static analysis rules and tooling for svnjn PHP...

27 1
calebdw/phpstan-laravel

A PHPStan extension for analysis of Laravel applications and packages.

10,458 33

Version History

Version Released PHP License
v1.1.0 ^8.4 MIT
v1.0.0 ^8.4 MIT