PHPackages                             galaxon/coding-standard - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. galaxon/coding-standard

ActivePhpcodesniffer-standard[Validation &amp; Sanitization](/categories/validation)

galaxon/coding-standard
=======================

PHP\_CodeSniffer coding standard extending PSR-12 with lowerCamelCase naming and modern PHP 8.4+ rules.

v1.2.0(1mo ago)0155MITPHPPHP ^8.4

Since Dec 9Pushed 1mo agoCompare

[ Source](https://github.com/mossy2100/Galaxon-PHP-Coding-Standard)[ Packagist](https://packagist.org/packages/galaxon/coding-standard)[ Docs](https://github.com/mossy2100/Galaxon-PHP-Coding-Standard)[ RSS](/packages/galaxon-coding-standard/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (10)Versions (7)Used By (5)

Galaxon PHP Coding Standard
===========================

[](#galaxon-php-coding-standard)

A PHP\_CodeSniffer coding standard for Galaxon PHP libraries extending PSR-12 with custom rules.

**[License](LICENSE)** | **[Changelog](CHANGELOG.md)**

[![PHP 8.4](docs/logo_php8_4.png)](docs/logo_php8_4.png)

---

Description
-----------

[](#description)

This package provides a custom PHP\_CodeSniffer coding standard for the Galaxon PHP libraries by Shaun Moss. It extends PSR-12 with additional rules for consistent naming conventions and modern PHP 8.4+ syntax.

**Key Features:**

- Extends PSR-12 coding standard
- Enforces `$lowerCamelCase` naming for variables, parameters, and properties
- Enforces consistent array formatting: single-line, grid, one-per-line, and associative with aligned arrows
- Removes unnecessary parentheses around class instantiation (PHP 8.4+)
- Enforces correct indentation for property hooks
- Automatic registration with PHP\_CodeSniffer

The package provides several custom sniffs to cover gaps in the available standards. These include:

- **Galaxon.Arrays.ArrayDeclaration**: Enforces consistent array formatting with lists and associative arrays
- **Galaxon.Classes.ClassInstantiationNoBrackets**: Removes unnecessary parentheses around class instantiation when accessing members (PHP 8.4+)
- **Galaxon.Classes.PropertyDeclaration**: Verifies property declarations, with PHP 8.4 property hook support
- **Galaxon.WhiteSpace.ScopeIndent**: Checks that control structures and code are indented correctly, with PHP 8.4 property hook support

See [Custom Sniffs](#custom-sniffs) for more details.

---

Development and Quality Assurance / AI Disclosure
-------------------------------------------------

[](#development-and-quality-assurance--ai-disclosure)

[Claude Chat](https://claude.ai) and [Claude Code](https://www.claude.com/product/claude-code) were used in the development of this package. The core classes were designed, coded, and commented primarily by the author, with Claude providing substantial assistance with code review, suggesting improvements, debugging, and generating tests and documentation. All code was thoroughly reviewed by the author, and validated using industry-standard tools including [PHP\_Codesniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/) and [PHPStan](https://phpstan.org/) (to level 9) to ensure full compliance with [PSR-12](https://www.php-fig.org/psr/psr-12/) coding standards. This collaborative approach resulted in a high-quality, thoroughly-tested, and well-documented package delivered in significantly less time than traditional development methods.

---

Requirements
------------

[](#requirements)

- PHP ^8.4
- squizlabs/php\_codesniffer ^4.0
- slevomat/coding-standard ^8.25
- dealerdirect/phpcodesniffer-composer-installer ^1.0

---

Installation
------------

[](#installation)

```
composer require --dev galaxon/coding-standard
```

The standard is automatically registered with PHP\_CodeSniffer via the `dealerdirect/phpcodesniffer-composer-installer` plugin.

---

Usage
-----

[](#usage)

Create a `phpcs.xml` file in your project root:

```

    Coding standard for my project

    src
    tests

```

Then run:

```
vendor/bin/phpcs        # Check for issues
vendor/bin/phpcbf       # Auto-fix issues
```

---

Included Sniffs
---------------

[](#included-sniffs)

The Galaxon coding standard extends PSR-12 and includes the following additional sniffs.

Links:

- [PSR-12 standard](https://www.php-fig.org/psr/psr-12/)
- PHP\_CodeSniffer provides the PSR-12, Generic, and Squiz sniffs. Documentation is found in the [repository](https://github.com/PHPCSStandards/PHP_CodeSniffer) and [wiki](https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki)
- [Slevomat coding standard repository and documentation](https://github.com/slevomat/coding-standard)

### Base Standard

[](#base-standard)

- **PSR-12**: Complete PSR-12 coding standard (with exception for multiple classes in test files)
    - `PSR2.Classes.PropertyDeclaration` excluded — replaced by `Galaxon.Classes.PropertyDeclaration` for PHP 8.4 property hook support (see [Custom Sniffs](#custom-sniffs))
    - `Generic.WhiteSpace.ScopeIndent` excluded — replaced by `Galaxon.WhiteSpace.ScopeIndent` for PHP 8.4 property hook support (see [Custom Sniffs](#custom-sniffs))

### Generic Sniffs

[](#generic-sniffs)

- **Generic.Arrays.DisallowLongArraySyntax**: Requires short array syntax `[]` instead of `array()`
- **Generic.Formatting.SpaceAfterCast**: Enforces no space after type casts (e.g. `(int)$value`)

### Squiz Sniffs

[](#squiz-sniffs)

- **Squiz.NamingConventions.ValidVariableName**: Enforces `$lowerCamelCase` for variables, parameters, and properties
- **Squiz.Strings.DoubleQuoteUsage.NotRequired**: Ensures strings use single quotes unless double quotes are necessary

### Slevomat Sniffs

[](#slevomat-sniffs)

#### Arrays

[](#arrays)

- **ArrayAccess**: Disallows whitespace between array access operators
- **DisallowImplicitArrayCreation**: Disallows implicit array creation
- **DisallowPartiallyKeyed**: Requires arrays to have keys for all or none of the values
- **SingleLineArrayWhitespace**: Checks whitespace in single-line array declarations

#### Attributes

[](#attributes)

- **AttributeAndTargetSpacing**: Enforces spacing between attributes and their targets
- **AttributesOrder**: Requires attributes to be ordered alphabetically
- **DisallowAttributesJoining**: Disallows joining multiple attributes with commas
- **DisallowMultipleAttributesPerLine**: Requires each attribute on its own line
- **RequireAttributeAfterDocComment**: Requires attributes to appear after doc comments

#### Classes

[](#classes)

- **BackedEnumTypeSpacing**: Enforces spacing around backed enum types
- **ClassConstantVisibility**: Requires visibility modifiers on class constants
- **ClassMemberSpacing**: Enforces spacing between class members
- **ConstantSpacing**: Enforces spacing around class constants
- **DisallowMultiConstantDefinition**: Disallows defining multiple constants in one statement
- **DisallowMultiPropertyDefinition**: Disallows defining multiple properties in one statement
- **DisallowStringExpressionPropertyFetch**: Disallows string expressions for property access
- **EmptyLinesAroundClassBraces**: Enforces no empty lines after opening or before closing class braces
- **EnumCaseSpacing**: Enforces spacing between enum cases
- **MethodSpacing**: Enforces spacing between methods
- **ModernClassNameReference**: Requires ::class syntax for class name references
- **PropertyDeclaration**: Enforces proper property declaration format including promoted properties
- **PropertySpacing**: Enforces spacing between properties
- **RequireMultiLineMethodSignature**: Requires multi-line format for long method signatures
- **RequireSelfReference**: Requires self:: instead of ClassName:: for self-references
- **RequireSingleLineMethodSignature**: Requires single-line format for short method signatures
- **TraitUseDeclaration**: Enforces proper trait use declaration format
- **TraitUseSpacing**: Enforces spacing around trait use statements

#### Commenting

[](#commenting)

- **AnnotationName**: Enforces correct annotation names
- **DeprecatedAnnotationDeclaration**: Enforces proper @deprecated annotation format
- **EmptyComment**: Disallows empty comments
- **RequireOneLineDocComment**: Requires one-line format for short doc comments
- **RequireOneLinePropertyDocComment**: Requires one-line format for short property doc comments
- **UselessInheritDocComment**: Disallows useless @inheritDoc comments

#### Control Structures

[](#control-structures)

- **AssignmentInCondition**: Disallows assignments in if, elseif, and do-while conditions
- **DisallowContinueWithoutIntegerOperandInSwitch**: Disallows continue without integer operand in switch
- **DisallowTrailingMultiLineTernaryOperator**: Requires leading operators in multi-line ternary expressions
- **LanguageConstructWithParentheses**: Requires parentheses for language constructs
- **RequireMultiLineCondition**: Requires multi-line format for long conditions with boolean operators
- **RequireMultiLineTernaryOperator**: Requires multi-line format for long ternary operators
- **RequireNullCoalesceEqualOperator**: Requires ??= operator when possible
- **RequireNullCoalesceOperator**: Requires ?? operator when possible
- **RequireNullSafeObjectOperator**: Requires ?-&gt; operator when possible
- **RequireSingleLineCondition**: Requires single-line format for short conditions
- **RequireShortTernaryOperator**: Requires short ternary operator ?: when possible
- **RequireTernaryOperator**: Requires ternary operator when possible
- **DisallowYodaComparison**: Disallows Yoda comparisons (constant === $variable)
- **UselessIfConditionWithReturn**: Disallows useless if conditions returning true or false

#### Exceptions

[](#exceptions)

- **DeadCatch**: Disallows empty catch blocks that don't handle exceptions
- **RequireNonCapturingCatch**: Requires catch without variable when exception is not used

#### Files

[](#files)

- **LineLength**: Enforces maximum line length of 120 characters

#### Functions

[](#functions)

- **ArrowFunctionDeclaration**: Enforces proper arrow function declaration format
- **DisallowEmptyFunction**: Disallows empty function bodies
- **FunctionLength**: Enforces maximum function length of 100 lines
- **RequireArrowFunction**: Requires arrow functions for simple closures
- **RequireMultiLineCall**: Requires multi-line format for long function calls
- **RequireSingleLineCall**: Requires single-line format for short function calls
- **NamedArgumentSpacing**: Enforces spacing around named arguments
- **DisallowTrailingCommaInCall**: Disallows trailing comma in function calls
- **DisallowTrailingCommaInClosureUse**: Disallows trailing comma in closure use statements
- **DisallowTrailingCommaInDeclaration**: Disallows trailing comma in function declarations
- **StaticClosure**: Requires static keyword for closures that don't use $this
- **StrictCall**: Enforces strict call\_user\_func\_array and call\_user\_func usage
- **UselessParameterDefaultValue**: Disallows useless parameter default values

#### Namespaces

[](#namespaces)

- **AlphabeticallySortedUses**: Requires use statements to be alphabetically sorted
- **DisallowGroupUse**: Disallows group use declarations
- **MultipleUsesPerLine**: Disallows multiple use statements on one line
- **NamespaceDeclaration**: Enforces proper namespace declaration format
- **NamespaceSpacing**: Enforces spacing around namespace declarations
- **ReferenceUsedNamesOnly**: Requires use statements for all referenced names
- **RequireOneNamespaceInFile**: Requires exactly one namespace per file
- **UnusedUses**: Disallows unused use statements including in annotations
- **UseDoesNotStartWithBackslash**: Disallows leading backslash in use statements
- **UseFromSameNamespace**: Disallows use statements from the same namespace
- **UseSpacing**: Enforces spacing between use statements
- **UselessAlias**: Disallows useless use statement aliases

#### Operators

[](#operators)

- **DisallowEqualOperators**: Disallows == and != operators, requires === and !==
- **NegationOperatorSpacing**: Enforces spacing around negation operator
- **RequireCombinedAssignmentOperator**: Requires combined assignment operators (+=, -=, etc.)
- **RequireOnlyStandaloneIncrementAndDecrementOperators**: Requires ++ and -- to be used standalone
- **SpreadOperatorSpacing**: Enforces spacing around spread operator

#### PHP

[](#php)

- **DisallowDirectMagicInvokeCall**: Disallows direct \_\_invoke() calls
- **ReferenceSpacing**: Enforces spacing around reference operator
- **ShortList**: Requires short list syntax \[\]
- **TypeCast**: Enforces proper type cast format
- **UselessSemicolon**: Disallows useless semicolons

#### Strings

[](#strings)

- **DisallowVariableParsing**: Disallows variable parsing in strings

#### Type Hints

[](#type-hints)

- **DeclareStrictTypes**: Requires declare(strict\_types=1)
- **ParameterTypeHintSpacing**: Enforces spacing around parameter type hints
- **ReturnTypeHintSpacing**: Enforces spacing around return type hints
- **LongTypeHints**: Requires long type hints (int instead of integer)
- **DNFTypeHintFormat**: Enforces DNF type format without spaces
- **NullableTypeForNullDefaultValue**: Requires nullable type for parameters with null default
- **ParameterTypeHint**: Requires parameter type hints
- **PropertyTypeHint**: Requires property type hints
- **ReturnTypeHint**: Requires return type hints
- **ClassConstantTypeHint**: Requires class constant type hints

#### Variables

[](#variables)

- **DisallowVariableVariable**: Disallows variable variables ($$var)
- **DuplicateAssignmentToVariable**: Disallows duplicate assignments to the same variable
- **UselessVariable**: Disallows useless variables

---

Variable and Property Naming Convention
---------------------------------------

[](#variable-and-property-naming-convention)

Ensures all variables, parameters, and properties use `$lowerCamelCase` format without leading underscores.

**Good:**

```
$userName = 'John';
$orderTotal = 100;
$isValid = true;
```

**Bad:**

```
$user_name = 'John';   // snake_case not allowed
$_private = 'value';   // leading underscore not allowed
$UserName = 'John';    // UpperCamelCase not allowed
```

PSR-12 and PER 3.0 do not mandate variable naming conventions. Specifically, from [PSR-1, Section 4.2 "Properties"](https://www.php-fig.org/psr/psr-1/#42-properties):

> This guide intentionally avoids any recommendation regarding the use of $StudlyCaps, $camelCase, or $under\_score property names. Whatever naming convention is used SHOULD be applied consistently within a reasonable scope. That scope may be vendor-level, package-level, class-level, or method-level.

In addition, from [PER Coding Style 3.0 Section 4.3 "Properties and Constants"](https://www.php-fig.org/per/coding-style/#43-properties-and-constants):

> Property or constant names MUST NOT be prefixed with a single underscore to indicate protected or private visibility. That is, an underscore prefix explicitly has no meaning.

Once upon a time, the convention was to use `$lower_snake_case` for variable names and properties; however, as the object-oriented features of PHP evolved, it became more common to use `$lowerCamelCase`, following the coding convention from Java. AI-generated code typically uses `$lowerCamelCase`, which is indicative of the trend. Therefore, given the requirement to be consistent, this sniff enforces the use of `$lowerCamelCase` for all variables, class properties, and function parameters.

Similarly, using an underscore prefix to indicate protected or private visibility was common practice in PHP until use of visibility modifiers became the standard. And now, the use of an underscore prefix is generally discouraged or disallowed.

This sniff is compliant with several PHP coding standards:

1. Symfony requires `$lowerCamelCase` ([ref](https://symfony.com/doc/current/contributing/code/standards.html#naming-conventions)).
2. Laravel requires `$lowerCamelCase` ([unofficially](https://spatie.be/guidelines/laravel-php#content-general-php-rules)).
3. Drupal variable names may use either `$lowerCamelCase` or `$lower_snake_case` ([ref](https://project.pages.drupalcode.org/coding_standards/php/coding/#functions-and-variables)), as long as one is consistent. Properties should use `$lowerCamelCase`, and protected or private properties should not use an underscore prefix. ([ref](https://project.pages.drupalcode.org/coding_standards/php/coding/#classes-methods-and-properties)).

Therefore, if any of the Galaxon packages are used in projects based on these frameworks, the code should be compliant.

---

Custom Sniffs
-------------

[](#custom-sniffs)

### Galaxon.Arrays.ArrayDeclaration

[](#galaxonarraysarraydeclaration)

Enforces consistent array formatting based on array type. The sniff differentiates between *lists* (no array keys appearing in the code), and *associative arrays* (at least one key appearing in the code). Technically, a list in PHP is any array with sequential integer keys starting from 0, but since we don't want to remove keys if they exist in the code, we treat any array with keys as an associative array and format it as such.

The format is chosen automatically based on array type, content, and length. Lists without nested arrays that fit on a single line (without overflowing the maximum line length and without multiline elements) use a compact single-line format — regardless of whether elements contain function calls or `new` expressions. Lists that don't fit on one line use grid format for simple values, or one-per-line for complex values (function/method calls, `new` expressions). Lists containing nested arrays always use one-per-line format. Associative arrays always use one key-value pair per line.

Array indentation defaults to 4 spaces per nesting level; this is configurable. The sniff uses `mb_strlen()` for proper Unicode character support when aligning arrows and grid padding. Values in associative arrays must start on the same line as the double arrow.

**Single-line lists**: Lists without nested arrays that fit on one line use a compact format with no trailing comma — including lists with function calls or `new` expressions.

```
// Good
$colors = ['red', 'green', 'blue'];
$results = [strlen('hi'), ucfirst('bye'), trim('x')];
$objects = [new Foo(), new Bar(), new Baz()];

// Bad
$colors = [
    'red',
    'green',
    'blue',
];
```

**Grid format**: Lists of simple values too long for a single line are arranged in a grid with uniform padding. A trailing comma is included.

```
// Good
$colors = [
    'red',     'green',   'blue',    'cyan',    'magenta', 'yellow',
    'black',   'white',   'orange',  'purple',  'brown',   'pink',
    'grey',    'navy',    'teal',
];
```

**One per line**: Lists too long for a single line that contain function/method calls or `new` expressions use one element per line with a trailing comma.

```
// Good
$results = [
    strtoupper('red'),
    strtolower('GREEN'),
    trim('  blue  '),
    substr('yellow', 0, 3),
];
```

**List of arrays**: Lists containing nested arrays always use one element per line, trailing comma required.

```
// Good
$points = [
    [1, 2],
    [3, 4],
    [5, 6],
];
```

**Associative arrays**: One key-value pair per line, arrows aligned, trailing comma required.

```
// Good
$user = [
    'name'  => 'John',
    'email' => 'john@example.com',
    'age'   => 30,
];

// Bad
$user = ['name' => 'John', 'email' => 'john@example.com', 'age' => 30];
```

**Configuration:**

PropertyTypeDefaultDescription`maxLineLength`int120Maximum line length before wrapping to grid or one-per-line format.`indent`int4Number of spaces to indent array elements.```

```

### Galaxon.Classes.ClassInstantiationNoBrackets

[](#galaxonclassesclassinstantiationnobrackets)

Removes unnecessary parentheses around `new` expressions when accessing members (PHP 8.4+).

PHP 8.4 introduced the ability to access properties and methods on newly instantiated objects without wrapping the instantiation in parentheses. This sniff enforces that modern syntax.

**Good:**

```
new DateTime()->format('Y-m-d');
new Foo()->method();
new Bar()->property;
```

**Bad:**

```
(new DateTime())->format('Y-m-d');  // Unnecessary parentheses
(new Foo())->method();              // Unnecessary parentheses
(new Bar())->property;              // Unnecessary parentheses
```

### Galaxon.Classes.PropertyDeclaration

[](#galaxonclassespropertydeclaration)

Verifies that properties are declared correctly. This is a replacement for `PSR2.Classes.PropertyDeclaration` that properly handles PHP 8.4 property hooks.

**Improvements over the PSR2 version:**

- Variables inside property hook bodies (e.g. `$this`, `$value`, local variables) are correctly ignored as non-property declarations.
- Properties with hooks end with a closing brace `}`, not a semicolon `;`, and are handled correctly.
- Supports PHP 8.4 asymmetric visibility (`public private(set)`), enforcing that read-visibility comes before write-visibility.
- Enforces correct ordering of modifiers: `abstract`/`final` before visibility, `static`/`readonly` after visibility.

### Galaxon.WhiteSpace.ScopeIndent

[](#galaxonwhitespacescopeindent)

Checks that control structures and code are indented correctly. This is a fork of `Generic.WhiteSpace.ScopeIndent` with PHP 8.4 property hook support.

PHP\_CodeSniffer's tokenizer does not recognise property hook braces as scope openers/closers, so the built-in `ScopeIndent` sniff cannot track their indentation. This sniff builds a map of property hook scopes (both the hook container `{ get ... set ... }` and individual hook bodies `get { ... }`) and tracks them alongside the standard scope stack.

**Good:**

```
class User
{
    public string $name {
        get {
            return $this->name;
        }
        set {
            $this->name = trim($value);
        }
    }
}
```

**Configuration:**

PropertyTypeDefaultDescription`indent`int4Number of spaces per indentation level.```

```

---

License
-------

[](#license)

MIT License - see [LICENSE](LICENSE) for details

---

Support
-------

[](#support)

- **Issues**:
- **Examples**: See `phpcs.xml` files in other Galaxon packages

For questions or suggestions, please [open an issue](https://github.com/mossy2100/PHP-CodingStandard/issues).

---

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for version history and changes.

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance90

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~22 days

Total

6

Last Release

50d ago

Major Versions

v0.3.0 → v1.0.02026-01-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/6f9cd1bb5c1b12882db4cb82161c1b5a22e1ccbad8845a54a6ae591647e88c07?d=identicon)[mossy2100](/maintainers/mossy2100)

---

Top Contributors

[![mossy2100](https://avatars.githubusercontent.com/u/371497?v=4)](https://github.com/mossy2100 "mossy2100 (28 commits)")

---

Tags

phpphpcsCode stylecodesnifferCoding Standardpsr-12linting

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/galaxon-coding-standard/health.svg)

```
[![Health](https://phpackages.com/badges/galaxon-coding-standard/health.svg)](https://phpackages.com/packages/galaxon-coding-standard)
```

###  Alternatives

[drupal/coder

Coder is a library to review Drupal code.

3043.6M461](/packages/drupal-coder)[consistence/coding-standard

Consistence - Coding Standard - PHP Code Sniffer rules

75833.3k94](/packages/consistence-coding-standard)[ninjify/coding-standard

Tuned &amp; very strict coding standards for PHP projects. Trusted by Contributte, Apitte, Nettrine and many others.

13497.1k13](/packages/ninjify-coding-standard)[mayflower/mo4-coding-standard

PHP CodeSniffer ruleset implementing the MO4 coding standards extending the Symfony coding standards.

17508.3k5](/packages/mayflower-mo4-coding-standard)[mreduar/laravel-phpcs

PHP Codesniffer ruleset to follow Laravel's coding style

3817.3k1](/packages/mreduar-laravel-phpcs)[leroy-merlin-br/coding-standard

The coding standard for PHP projects on LMBR

2137.0k10](/packages/leroy-merlin-br-coding-standard)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
