PHPackages                             bestit/php\_codesniffer - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. bestit/php\_codesniffer

Abandoned → [best-it/php\_codesniffer](/?search=best-it%2Fphp_codesniffer)Library[Testing &amp; Quality](/categories/testing)

bestit/php\_codesniffer
=======================

PHP\_CodeSniffer ruleset and custom rules from best it.

4.0.0(3y ago)1438.8k8[6 issues](https://github.com/bestit/PHP_CodeSniffer/issues)[2 PRs](https://github.com/bestit/PHP_CodeSniffer/pulls)5MITPHPPHP &gt;=8.0CI failing

Since Jun 7Pushed 2y ago7 watchersCompare

[ Source](https://github.com/bestit/PHP_CodeSniffer)[ Packagist](https://packagist.org/packages/bestit/php_codesniffer)[ RSS](/packages/bestit-php-codesniffer/feed)WikiDiscussions main Synced 3d ago

READMEChangelog (10)Dependencies (10)Versions (60)Used By (5)

best it PHP\_CodeSniffer
========================

[](#best-it-php_codesniffer)

[![Build Status](https://camo.githubusercontent.com/068b046501393bd484c962af0b39ccf80d25e7834e1c7ae94ee6823364fbc058/68747470733a2f2f7472617669732d63692e636f6d2f6265737469742f5048505f436f6465536e69666665722e7376673f6272616e63683d6d61696e)](https://travis-ci.com/bestit/php_codesniffer) [![Build Status](https://camo.githubusercontent.com/e45197a3780259711d4d2f2c7e5e8c61e63ea58e062133851fd24170bda96fac/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6265737469742f5048505f436f6465536e69666665722f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/bestit/PHP_CodeSniffer/build-status/master) [![Scrutinizer Code Quality](https://camo.githubusercontent.com/44cb47023a45d28a25bd00708e01c8cadc8ee1bb7fa030a3b1d56cf810c409ee/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6265737469742f5048505f436f6465536e69666665722f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/bestit/PHP_CodeSniffer/?branch=main) [![Code Coverage](https://camo.githubusercontent.com/93e84c6ecf6415fff4a54246700f42c628d38b35cfb15b36252a2733afecb029/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6265737469742f5048505f436f6465536e69666665722f6261646765732f636f7665726167652e706e673f623d6d61696e)](https://scrutinizer-ci.com/g/bestit/PHP_CodeSniffer/?branch=main)

This package contains a default rule set and custom rules which are used in all best it projects.

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

[](#installation)

Our PHP\_CodeSniffer package can be installed with composer with the following command:

```
composer require best-it/php_codesniffer --dev
```

**Please use Version 1 for PHP 7.0!**

Usage
-----

[](#usage)

Create a PHP\_CodeSniffer configuration (phpcs.xml.dist / phpcs.xml) like this:

```

    The coding standard for project x.

    src/
    tests/

```

If you want to sniff for special PHP Versions just declare a ["testVersion"](https://github.com/PHPCompatibility/PHPCompatibility#using-a-custom-ruleset) like:

```

```

and include

```

```

after you included our ruleset. (Don't forget to dev-require *phpcompatibility/php-compatibility:^9.0*.)

Execute the PHP\_CodeSniffer (path can vary on your composer configuration):

```
./vendor/bin/phpcs
```

We use warnings for things which a human person should check, but which must not fail an automatic build. If you want to see warnings but get successful builds, call the code sniffer with the special config option *ignore\_warnings\_on\_exit*:

```
./vendor/bin/phpcs --config-set ignore_warnings_on_exit 1
```

or, if you want the option only for a single run:

```
./vendor/bin/phpcs --runtime-set ignore_warnings_on_exit 1
```

[Check original docs for more info.](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#ignoring-warnings-when-generating-the-exit-code)

If you want to ignore warnings altogether, you can provide the cli argument n:

```
./vendor/bin/phpcs -n
```

We suggest that you do not ignore warnings, but only check them in a manual pull/merge request.

### Use in PHPStorm

[](#use-in-phpstorm)

How to use it in our favorite IDE?

/File/Settings:

1. [![Choose executable](./docs/exe.png "Executable")](./docs/exe.png)
2. [![Set up inspection](./docs/inspection.png "Inspection")](./docs/inspection.png)
3. ... and choose our ruleset.

Used sniffs
-----------

[](#used-sniffs)

The base for the BestIt Standard is [PSR-12](https://github.com/php-fig/fig-standards/blob/master/proposed/extended-coding-style-guide.md).

SniffDescriptionsuppressableBestIt.Classes.ModernClassNameReference.ClassNameReferencedViaFunctionCallYou MUST use ::class instead of functions.noBestIt.Classes.ModernClassNameReference.ClassNameReferencedViaMagicConstantYou MUST use ::class instead of **CLASS**.noBestIt.Commenting.ClassDoc.DocCommentUcFirstEvery doc comment block SHOULD start ucfirst.noBestIt.Commenting.ClassDoc.NoLineAfterDocCommentEvery doc comment block (the summary or a long description paragrah) SHOULD finish with double newline.noBestIt.Commenting.ClassDoc.NoSummaryThere MUST be a summary.noBestIt.Commenting.ClassDoc.SummaryTooLongThe summary SHOULD be in one line.noBestIt.Commenting.ConstantDoc.DocCommentUcFirstEvery doc comment block SHOULD start ucfirst.noBestIt.Commenting.ConstantDoc.NoLineAfterDocCommentEvery doc comment block (the summary or a long description paragrah) SHOULD finish with double newline.noBestIt.Commenting.ConstantDoc.NoSummaryThere MUST be a summary.noBestIt.Commenting.ConstantDoc.SummaryTooLongThe summary SHOULD be in one line.noBestIt.Commenting.EmptyLinesDoc.EmptyLinesFoundThere MUST be no redundant lines in your doc block.noBestIt.Commenting.FunctionDoc.DocCommentUcFirstEvery doc comment block SHOULD start ucfirst.noBestIt.Commenting.FunctionDoc.NoLineAfterDocCommentEvery doc comment block (the summary or a long description paragrah) SHOULD finish with double newline.noBestIt.Commenting.FunctionDoc.NoSummaryThere MUST be a summary.noBestIt.Commenting.FunctionDoc.SummaryTooLongThe summary SHOULD be in one line.noBestIt.Commenting.PropertyDoc.DocCommentUcFirstEvery doc comment block SHOULD start ucfirst.noBestIt.Commenting.PropertyDoc.NoLineAfterDocCommentEvery doc comment block (the summary or a long description paragrah) SHOULD finish with double newline.noBestIt.Commenting.PropertyDoc.NoSummaryThere MUST be a summary.noBestIt.Commenting.PropertyDoc.SummaryTooLongThe summary SHOULD be in one line.noBestIt.Commenting.RedundantWhitespace.RedundantWhitespaceThere MUST be no additonal spaces around your doc tags.noBestIt.Comparisons.EmptyArrayForComparison.EmptyArrayYou MUST not create an empty array, to check for an empty array.noBestIt.Comparisons.EqualOperator.EqualOperatorFoundYou MUST use the "Identical" operator (===).yesBestIt.Comparisons.ParasOfNegativeInstanceOf.ParasAroundNegativeInstanceOfMissingYou MUST provide parentheses around your negative instanceof check.noBestIt.DocTags.AuthorTag.TagContentFormatInvalidYou MUST commit to your codes and give an [author tag](http://docs.phpdoc.org/references/phpdoc/tags/author.html).noBestIt.DocTags.DeprecatedTag.MissingDatesThe error code for the missing dates.noBestIt.DocTags.DeprecatedTag.TagContentFormatInvalidIf you provide a deprecated tag, you MUST provide it with versions since when its deprecated and when it will be removed.noBestIt.DocTags.DisallowedClassTags.TagNotAllowedYou MUST not give one of the disallowed tags in your doc comment.noBestIt.DocTags.DisallowedConstantTags.TagNotAllowedYou MUST not give one of the disallowed tags in your doc comment.noBestIt.DocTags.DisallowedMethodTags.TagNotAllowedYou MUST not give one of the disallowed tags in your doc comment.noBestIt.DocTags.DisallowedPropertyTags.TagNotAllowedYou MUST not give one of the disallowed tags in your doc comment.noBestIt.DocTags.PackageTag.TagContentFormatInvalidYou MUST provide a special tag format.noBestIt.DocTags.PackageTag.WrongPackageIf there is a namespace, you MUST provide this namespace as package tag.noBestIt.DocTags.ParamTag.MissingDescYou SHOULD provide a description for your parameter.noBestIt.DocTags.ParamTag.MissingTypeYou MUST provide a type for your param tag.noBestIt.DocTags.ParamTag.MissingVariableYour method MUST have a matching variable for your param tag.noBestIt.DocTags.ParamTag.MissingVariablesYour method MUST have parameters if there is a param tag.noBestIt.DocTags.ParamTag.MixedTypeYou SHOULD prevent the mixed type and try to provide native types.noBestIt.DocTags.ParamTag.TagContentFormatInvalidYou MUST provide a special tag format.noBestIt.DocTags.RequiredClassTags.TagOccurrenceMaxYou MUST provide only the maximum amount of required tags. For example, only one return per method is allowed. The error is registered for every tag specifically.noBestIt.DocTags.RequiredClassTags.TagOccurrenceMinYou MUST provide the required tags. The error is registered for every tag specifically.noBestIt.DocTags.RequiredMethodTags.TagOccurrenceMaxYou MUST provide only the maximum amount of required tags. For example, only one return per method is allowed. The error is registered for every tag specifically.noBestIt.DocTags.RequiredMethodTags.TagOccurrenceMinYou MUST provide the required tags. The error is registered for every tag specifically.noBestIt.DocTags.RequiredPropertyTags.TagOccurrenceMaxYou MUST provide only the maximum amount of required tags. For example, only one return per method is allowed. The error is registered for every tag specifically.noBestIt.DocTags.RequiredPropertyTags.TagOccurrenceMinYou MUST provide the required tags. The error is registered for every tag specifically.noBestIt.DocTags.TagSorting.MissingNewlineBetweenTagsYou SHOULD separate tag groups and the final return with a newline.yes by classBestIt.DocTags.TagSorting.WrongTagSortingYou SHOULD sort the tags by their occurrence and then alphabetically, but @return SHOULD be the last.yes by classBestIt.DocTags.ThrowsTag.MissingThrowDescriptionYou SHOULD provide a description your throw tag.noBestIt.DocTags.ThrowsTag.TagContentFormatInvalidYou MUST provide a special tag format.noBestIt.DocTags.VarTag.TagContentFormatInvalidYou MUST provide a type for your var tag.noBestIt.DocTags.VersionTag.TagContentFormatInvalidIf you provide a version tag, you MUST provide it in [semver 2.0-Format](https://semver.org) with Major.Minor.Patch-Version .noBestIt.Formatting.AlphabeticClassContent.SortAlphabeticallyYou SHOULD sort you constants, methods and properties alphabetically.noBestIt.Formatting.AlphabeticallySortedUses.IncorrectlyOrderedUsesYou MUST provide your imports in alphabetically order, PSR-12 compatible.no(BestIt.Formatting.NoWhitespaceAfterClassOpening.IncorrectEmptyLinesAfterOpeningBraceThere MUST be no lines after the opening brace.no(BestIt.Formatting.NoWhitespaceAfterClassOpening.IncorrectEmptyLinesBeforeClosingBraceThere MUST be no lines before the closing brace.noBestIt.Formatting.OpenTag.LineNotEmptyThe next line after the open tag MUST be empty.noBestIt.Formatting.OpenTag.NoSpaceAfterOpenTagThere MUST be whitespace after the open tag.noBestIt.Formatting.OpenTag.OpenTagNotFirstStatementAfter the open tag there MUST be an empty line.noBestIt.Formatting.ReturnTypeHintSpacingSniff.NoSpaceBetweenColonAndTypeHintThere MUST be no whitespace after the return type colon.BestIt.Formatting.ReturnTypeHintSpacingSniff.WhitespaceBeforeColonThere MUST be no whitespace before the return type colon.BestIt.Formatting.TrailingArrayComma.MissingTrailingCommaYou MUST add a trailing comma to your multi line arrays.noBestIt.Formatting.TrailingCommaInDeclaration.MissingTrailingCommaEnforces a trailing command in method declaration if there is a line wrap.noBestIt.Formatting.TraitUseDeclaration.MultipleTraitsPerDeclarationYou MUST provide only one "use" per Line for importing traits etc. in classes.noBestIt.Formatting.UCVFSorting.WrongPositionYou MUST sort the contents of your classes, traits, interface, etc. in the following order: T\_USE, T\_CONST, T\_VARIABLE, T\_FUNCTION.noBestIt.Functions.FluentSetter.MustReturnThisEvery setter function MUST return $this if nothing else is returned.noBestIt.Functions.FluentSetter.NoReturnFoundYour method MUST contain a return.yesBestIt.Functions.ForbiddenFunctions.DiscouragedYou SHOULD not use eval.yesBestIt.Functions.ForbiddenFunctions.DiscouragedWithAlternativeYou SHOULD not use alias but the original function names.yesBestIt.Functions.MultipleReturn.MultipleReturnsFoundYou SHOULD only use a return per method.noBestIt.Functions.NoNamedArguments.DisallowedNamedArgumentYou MUST not use named arguments.noBestIt.Functions.NoSimplePropertyMethod.ShouldUseTypedPropertyDirectlyYou SHOULD use the typed property directly instead of the the simple getter-/setter-combination.yesBestIt.Functions.TrailingCommaInCall.MissingTrailingCommaYou MUST append a trailing command in your multi line function calls.noBestIt.NamingConventions.CamelCaseVariable.NotCamelCaseYou MUST provide your vars in camel case, lower case first.yesBestIt.Spacing.ClassMemberSpacing.IncorrectCountOfBlankLinesBetweenMembersClass members MUST be separated with one line.noBestIt.Spacing.ConstantSpacing.IncorrectCountOfBlankLinesAfterConstantA constant MUST be separated with one line.noBestIt.Spacing.NamespaceSpacing.IncorrectLinesCountAfterNamespaceThere MUST be one line after the namespace.noBestIt.Spacing.NamespaceSpacing.IncorrectLinesCountBeforeNamespaceThere MUST be one line before the namespace.noBestIt.Spacing.PropertySpacing.IncorrectCountOfBlankLinesAfterPropertyThere MUST be one line after a property.noBestIt.Spacing.SpaceAfterDeclare.GroupBlankLineFoundMultiple declare-statements SHOULD be grouped without a blank line.noBestIt.Spacing.SpaceAfterDeclare.MuchWhitespaceFoundTHERE MUST be just one single line after the declare statement.noBestIt.Spacing.SpaceAfterDeclare.NoWhitespaceFoundThere MUST be one empty line after declare-statement.noBestIt.Spacing.SpaceAroundConcat.MissingSpaceAroundConcatYou MUST wrap your concat-dot with a whitespace char.noBestIt.Spacing.TraitUseSpacing.IncorrectLinesCountAfterLastUseYou MUST not provide additional lines after your last rait usage.noBestIt.Spacing.TraitUseSpacing.IncorrectLinesCountBeforeFirstUseYou MUST not provide additional new lines before your first trait use.noBestIt.Spacing.TraitUseSpacing.IncorrectLinesCountBetweenUsesYou MUST not provide additional new lines between trait usages.noBestIt.Spacing.UseSpacing.IncorrectLinesCountAfterLastUseThere MUST be one line after the last usage.noBestIt.Spacing.UseSpacing.IncorrectLinesCountBeforeFirstUseThere MUST be one line before the first usage.noBestIt.Spacing.UseSpacing.IncorrectLinesCountBetweenDifferentTypeOfUseThere must be no line betweeen different usages.noBestIt.Spacing.UseSpacing.IncorrectLinesCountBetweenSameTypeOfUseThe MUST be no line between same usages.noBestIt.Strings.ConcatCalculationSniff.CalculationWithoutBracketsYou MUST encapsulate your calculation with brackets.noBestIt.TypeHints.ExplicitAssertions.RequiredExplicitAssertionUse assertion instead of inline documentation comment.noBestIt.TypeHints.PropertyTypeHint.MissingAnyTypeHintMUST have any type hint if possible.yesBestIt.TypeHints.PropertyTypeHint.MissingNativeTypeHintMUST have a native type hint (matching the doc block.)yesBestIt.TypeHints.ReturnTypeDeclaration.MissingReturnTypeHintEvery function or method MUST have a type hint if the return annotation is valid.yesBestIt.TypeHints.SuggestExplicitReturnType.MixedTypeYou SHOULD not use a mixed type but an explicit native return type.yesGeneric.Formatting.SpaceAfterCastThere MUST be a space after cast.Generic.Arrays.DisallowLongArraySyntaxEvery array syntax MUST be in short array syntax.SlevomatCodingStandard.Classes.ClassConstantVisibility.MissingConstantVisibilityConstants MUST be marked with a visibility.SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedNameNo class may be used via its FQCN. You MUST import every class!SlevomatCodingStandard.TypeHints.DeclareStrictTypesEvery file MUST have "declare(strict\_types=1);" two line breaks after the opening tag. There MUST be no spaces aroung the equal-sign.Squiz.Strings.DoubleQuoteUsageEvery String MUST be wrapped with single quotes.Development
-----------

[](#development)

### Introduction

[](#introduction)

The code sniffer is based on a [token-based](http://php.net/manual/de/tokens.php) sniff mechanism.

You can use the [verbose-options](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage#printing-progress-information)of the code sniffer cli, to see which tokens are parsed on which position in your file. Please consult the [official code sniffer tutorial](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial)to know the theory how to code a custom sniff.

The gist of this tutorial is, that you need to implement the interface *PHP\_CodeSniffer\\Sniffs\\Sniff* which enforces two methods:

#### 1. Token Registration

[](#1-token-registration)

The *register*-method should return the parser token id of the tokens, which you want to sniff.

#### 2. Process

[](#2-process)

The *process*-method is called with the position of your registered token in the token stack of the given file object.

best it "Helpers"
-----------------

[](#best-it-helpers)

### BestIt\\Sniffs\\AbstractSniff

[](#bestitsniffsabstractsniff)

We refactored our basic work into this abstract. You can use an extended api to get a cleaner api and skips simple boilerplating.

- **areRequirementsMet**: If this method returns false, the sniff is "skipped".
- **isSniffSuppressed**: If this method returns true, the annotation for suppression is given and the sniff should be "skipped".
- **processToken**: The boilerplate of the normal api is saved in object properties and you can sniff you token without the need to "re-implement" the basic interface with its method arguments.
- **setUp**: You can set up the test, before the requirements are checked with *areRequirementsMet*.
- **tearDown**: If you want to "destroy" this sniff, you can tear it down after the sniff processing.

**The CodeSniffer is meant to be stateless even if the sniff-classes are used as "singletons". So if you save a state in your sniff, you MUST tearDown afterwards or initialize correctly in the setUp.**

### BestIt\\Sniffs\\DocTags\\AbstractTagSniff

[](#bestitsniffsdoctagsabstracttagsniff)

This abstract class helps you sniff for single doc tags. Just implement the given abstract methods and you can register and sniff for a specific doc tag and check for its content till a newline.

#### BestIt\\Sniffs\\DocTags\\TagContentFormatTrait

[](#bestitsniffsdoctagstagcontentformattrait)

This trait is meant in addition to the AbstractTagSniff and provides you with an api, which checks the tag content automatically against a regex pattern, which leads to an error or warning with the code *TagContentFormatInvalid*.

### BestIt\\Sniffs\*RegistrationTrait

[](#bestitsniffsregistrationtrait)

We provide some traits, which make it easier, to register sniffs for class-like structures, constants, methods and properties.

Testing
-------

[](#testing)

### Requirements

[](#requirements)

**To be able to test our written sniffs ensure that composer is installed with the option `--prefer-source`. This is needed because we use the TestCase of the SlevomatCodingStandard.**

### Error code as public constant

[](#error-code-as-public-constant)

In additional to readable/clean clode our test base requires you to provide your error codes as a public constant prefixed with **CODE\_** in your sniff class.

### No "Test"-Namespace

[](#no-test-namespace)

Our test base expects you to provide everything in the "normal" namespace: *BestIt*.

### Helping test traits

[](#helping-test-traits)

#### Token Registration

[](#token-registration)

The trait *BestIt\\Sniffs\\TestTokenRegistrationTrait* helps you with testing of the registered tokens.

#### Public error codes

[](#public-error-codes)

The trait *BestIt\\Sniffs\\TestRequiredConstantsTrait* helps you to test the errors codes. We suggest that you test the values as well, because they could be part of a "foreign ruleset" out of your control from your "customer." So we enforce that the constant values stay api-stable!

#### Default Integration Tests

[](#default-integration-tests)

The trait *BestIt\\Sniffs\\DefaultSniffIntegrationTestTrait* provides you with three tests to test the usually use cases of a sniff based on sniff-individual test files:

1. testCorrect
2. testErrors
3. testWarnings

##### Requirements

[](#requirements-1)

- Your test-file should be called exactly like your sniff (including the namespace) but suffixed with ***Test***
- Provide a folder ***Fixtures*** as a sibling to your test file.
- Put a folder into your "Fixtures" directory, which is called exactly like the short name of the sniff.

##### testCorrect

[](#testcorrect)

Create a ***correct*** folder into your fixtures directory. Every php file in this folder will be checked against your sniff. The sniff may not populate errors and warning for a successful test!

##### testErrors

[](#testerrors)

Create a ***with\_errors*** folder into your fixtures directory. Every php file in this folder should trigger an error in your sniff. You must provide the error structure through the file name. The file name must match the following pregex:

```
/(?P[\w]+)(\(\w*\))?\.(?P[\d-\,]+)(?P\.fixed)?\.php/
```

The file name gives information about which errors in which line should occur. Example files would be *ErrorCode.1.php, ErrorCode.1,2,3.php, ErrorCode.1,2,3.fixed.php*, ErrorCode(2).1,2,3.php, ErrorCode(2).1,2,3.fixed.php\_. The error code must be the original code value from your sniff, the numbers after the first dot are the erroneous lines.

If you provide an additional file which is suffixed with "fixed" then this is the correct formatted file for its erroneous sibling.

##### testWarnings

[](#testwarnings)

Create a ***with\_warnings*** folder into your fixtures directory. Every php file in this folder should trigger a warning in your sniff. You must provide the warning structure through the file name. The file name must match the following pregex:

```
/(?P[\w]+)(\(\w*\))?\.(?P[\d-\,]+)(?P\.fixed)?\.php/
```

The file name gives information about which warning in which line should occur. Example files would be *WarningCode.1.php, WarningCode.1,2,3.php, WarningCode.1,2,3.fixed.php*, WarningCode(2).1,2,3.php, WarningCode(2).1,2,3.fixed.php\_. The warning code must be the original code value from your sniff, the numbers after the first dot are the lines with warnings.

If you provide an additional file which is suffixed with "fixed" then this is the correct formatted file for its erroneous sibling.

Contributing
------------

[](#contributing)

See [CONTRIBUTING.md](CONTRIBUTING.md).

### Semantic Versioning

[](#semantic-versioning)

We use [semantic versioning](https://semver.org) in correlation with the style enforced by our ruleset and not directly with our source code. This means, that there could be breaking change in our code, but as long as the style is not changed heavily, then the breaking change will not be mirrored in our version number:

- Patch-Version (last number): backwards-compatible bugfixes in our ruleset
- Minor-Version (middle number): backwards-compatible features in our ruleset (just warnings, deletions or auto-fixable errors)
- Major-Version (first number): breaking change in our ruleset

**We optimize our versioning for the usage of the sniffer, not for the development!**

TODO
----

[](#todo)

- Remove further slevomat dependencies for internal apis.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance11

Infrequent updates — may be unmaintained

Popularity33

Limited adoption so far

Community28

Small or concentrated contributor base

Maturity82

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 79% 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 ~43 days

Recently: every ~124 days

Total

50

Last Release

1128d ago

Major Versions

1.2.2 → 2.0.32019-04-01

1.2.3 → 3.0.02020-02-05

1.2.4 → 3.1.02020-06-09

2.1.0 → 3.3.02020-09-14

3.x-dev → 4.0.0-RC12021-12-05

PHP version history (7 changes)0.2.0PHP ^7.0

0.3.0PHP ^7.1

1.2.0PHP 7.0.\*

3.0.0PHP ^7.4

2.0.4PHP &gt;=7.1 &lt;7.4

3.4.0PHP &gt;=7.4

4.0.0-RC1PHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/acc5af332f2a79dedb5aea83c3b4c2665d99fd2c14743fd0c2a3d70ecf0b7859?d=identicon)[best-it](/maintainers/best-it)

---

Top Contributors

[![b3nl](https://avatars.githubusercontent.com/u/1861864?v=4)](https://github.com/b3nl "b3nl (124 commits)")[![bestit-lubisch](https://avatars.githubusercontent.com/u/20165267?v=4)](https://github.com/bestit-lubisch "bestit-lubisch (11 commits)")[![nhardeweg](https://avatars.githubusercontent.com/u/16148081?v=4)](https://github.com/nhardeweg "nhardeweg (10 commits)")[![bestit-mbe](https://avatars.githubusercontent.com/u/36737979?v=4)](https://github.com/bestit-mbe "bestit-mbe (3 commits)")[![tim-kellner](https://avatars.githubusercontent.com/u/15520044?v=4)](https://github.com/tim-kellner "tim-kellner (2 commits)")[![migo315](https://avatars.githubusercontent.com/u/13180135?v=4)](https://github.com/migo315 "migo315 (2 commits)")[![bestit-el-bardan](https://avatars.githubusercontent.com/u/24458969?v=4)](https://github.com/bestit-el-bardan "bestit-el-bardan (1 commits)")[![damyanovg](https://avatars.githubusercontent.com/u/32706870?v=4)](https://github.com/damyanovg "damyanovg (1 commits)")[![nlubisch](https://avatars.githubusercontent.com/u/3511228?v=4)](https://github.com/nlubisch "nlubisch (1 commits)")[![stefanhaelingbestit](https://avatars.githubusercontent.com/u/40687864?v=4)](https://github.com/stefanhaelingbestit "stefanhaelingbestit (1 commits)")[![GM-Alex](https://avatars.githubusercontent.com/u/1454864?v=4)](https://github.com/GM-Alex "GM-Alex (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/bestit-php-codesniffer/health.svg)

```
[![Health](https://phpackages.com/badges/bestit-php-codesniffer/health.svg)](https://phpackages.com/packages/bestit-php-codesniffer)
```

###  Alternatives

[wp-cli/wp-cli-tests

WP-CLI testing framework

422.7M87](/packages/wp-cli-wp-cli-tests)[consistence/coding-standard

Consistence - Coding Standard - PHP Code Sniffer rules

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

PHP\_CodeSniffer rules (sniffs) for Acquia coding standards

214.8M28](/packages/acquia-coding-standards)[moxio/php-codesniffer-sniffs

Custom sniffs for PHP\_CodeSniffer

18283.0k3](/packages/moxio-php-codesniffer-sniffs)[best-it/php_codesniffer

PHP\_CodeSniffer ruleset and custom rules from best it.

15137.3k6](/packages/best-it-php-codesniffer)[protonlabs/php-coding-standard

ProtonLabs Coding Standard

1151.5k1](/packages/protonlabs-php-coding-standard)

PHPackages © 2026

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