Giter Club home page Giter Club logo

codingstandard's Introduction

Coding Standard

Build Status Downloads

Set of PHP_CodeSniffer Sniffs and PHP-CS-Fixer Fixers used by Symplify projects.

They run best with EasyCodingStandard.

Install

composer require symplify/coding-standard --dev

Rules Overview

  • Rules with ๐Ÿ”ง are configurable.

Make sure That @param, @var, @return and @throw Types Exist

services:
    Symplify\CodingStandard\Sniffs\Commenting\AnnotationTypeExistsSniff: ~

โŒ

<?php

class SomeClass
{
    /**
     * @var NonExistingClass
     */
    private $property;
}

๐Ÿ‘

<?php

class SomeClass
{
    /**
     * @var ExistingClass
     */
    private $property;
}

Make @param, @return and @var Format United

services:
    Symplify\CodingStandard\Fixer\Commenting\ParamReturnAndVarTagMalformsFixer: ~
 <?php

 /**
- * @param $name string
+ * @param string $name
- * @return int $value
+ * @return int
  */
 function someFunction($name)
 {
 }

 class SomeClass
 {
     /**
-     * @var int $property
+     * @var int
      */
     private $property;
 }

-/* @var int $value */
+/** @var int $value */
 $value = 5;

-/** @var $value int */
+/** @var int $value */
 $value = 5;

Remove // end of ... Legacy Comments

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Commenting\RemoveEndOfFunctionCommentFixer: ~
 <?php

 function someFunction()
 {

-} // end of someFunction
+}

Order Private Methods by Their Use Order

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Order\PrivateMethodOrderByUseFixer: ~

โŒ

<?php

class SomeClass
{
    public function run()
    {
        $this->call1();
        $this->call2();
    }

    private function call2()
    {
    }

    private function call1()
    {
    }
}

๐Ÿ‘

<?php

class SomeClass
{
    public function run()
    {
        $this->call1();
        $this->call2();
    }

    private function call1()
    {
    }

    private function call2()
    {
    }
}

Order Properties From Simple to Complex

Properties are ordered by visibility first, then by complexity.

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Order\PropertyOrderByComplexityFixer: ~

โŒ

<?php

final class SomeFixer
{
    /**
     * @var string
     */
    private $name;

    /**
     * @var Type
     */
    private $service;

    /**
     * @var int
     */
    private $price;
}

๐Ÿ‘

<?php

final class SomeFixer
{
    /**
     * @var int
     */
    private $price;

    /**
     * @var string
     */
    private $name;

    /**
     * @var Type
     */
    private $service;
}

Prefer Another Class

# ecs.yml
services:
    Symplify\CodingStandard\Sniffs\Architecture\PreferredClassSniff:
        oldToPreferredClasses:
            DateTime: 'Nette\Utils\DateTime'

โŒ

<?php

$dateTime = new DateTime('now');

๐Ÿ‘

<?php

$dateTime = new Nette\Utils\DateTime('now');

Indexed PHP arrays should have 1 item per line

-$friends = [1 => 'Peter', 2 => 'Paul'];
+$friends = [
+    1 => 'Peter',
+    2 => 'Paul'
+];

There should not be empty PHPDoc blocks

Just like PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer, but this one removes all doc block lines.

-/**
- */
 public function someMethod()
 {
 }

Block comment should only contain useful information about types

 /**
- * @param int $value
- * @param $anotherValue
- * @param SomeType $someService
- * @return array
  */
 public function setCount(int $value, $anotherValue, SomeType $someService): array
 {
 }

This checker keeps 'mixed' and 'object' and other types by default. But if you need, you can configure it:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Commenting\RemoveUselessDocBlockFixer:
        useless_types: ['mixed', 'object'] # [] by default

Block comment should not have 2 empty lines in a row

 /**
  * @param int $value
  *
- *
  * @return array
  */
 public function setCount($value)
 {
 }

Include/Require should be followed by absolute path

-require 'vendor/autoload.php';
+require __DIR__.'/vendor/autoload.php';

Parameters, arguments and array items should be on the same/standalone line to fit line length

 class SomeClass
 {
-    public function someMethod(SuperLongArguments $superLongArguments, AnotherLongArguments $anotherLongArguments, $oneMore)
+    public function someMethod(
+        SuperLongArguments $superLongArguments,
+        AnotherLongArguments $anotherLongArguments,
+        $oneMore
+    )
     {
     }

-    public function someOtherMethod(
-        ShortArgument $shortArgument,
-        $oneMore
-    ) {
+    public function someOtherMethod(ShortArgument $shortArgument, $oneMore) {
     }
 }
  • Are 120 characters too long for you?
  • Do you want to break longs lines but not inline short lines or vice versa?

Change it:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer:
        max_line_length: 100 # default: 120
        break_long_lines: true # default: true
        inline_short_lines: false # default: true

Property name should match its key, if possible

-public function __construct(EntityManagerInterface $eventManager)
+public function __construct(EntityManagerInterface $entityManager)
 {
-    $this->eventManager = $eventManager;
+    $this->entityManager = $entityManager;
 }

This checker ignores few system classes like std* or Spl* by default. In case want to skip more classes, you can configure it:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
        extra_skipped_classes:
            - 'MyApp*' # accepts anything like fnmatch

Public Methods Should have Specific Order by Interface/Parent Class

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Order\MethodOrderByTypeFixer:
        method_order_by_type:
            Rector\Contract\Rector\PhpRectorInterface:
                - 'getNodeTypes'
                - 'refactor'

โ†“

 final class SomeRector implements PhpRectorInterface
 {
-    public function refactor()
+    public function getNodeTypes()
     {
-        // refactoring
+        return ['SomeType'];
     }
-
-    public function getNodeTypes()
+    public function refactor(): void
     {
-        return ['SomeType'];
+        // refactoring
     }
 }

::class references should be used over string for classes and interfaces

-$className = 'DateTime';
+$className = DateTime::class;

This checker takes only existing classes by default. In case want to check another code not loaded by local composer, you can configure it:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer:
        class_must_exist: false # true by default

Do you want to allow some classes to be in string format?

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer:
        allow_classes:
            - 'SomeClass'

Array property should have default value, to prevent undefined array issues

 class SomeClass
 {
     /**
      * @var string[]
      */
-    public $apples;
+    public $apples = [];

     public function run()
     {
         foreach ($this->apples as $mac) {
             // ...
         }
     }
 }

Strict types declaration has to be followed by empty line

 <?php declare(strict_types=1);
+
 namespace SomeNamespace;

Non-abstract class that implements interface should be final

Except for Doctrine entities, they cannot be final.

-class SomeClass implements SomeInterface
+final class SomeClass implements SomeInterface
 {
 }

In case want check this only for specific interfaces, you can configure them:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Solid\FinalInterfaceFixer:
        only_interfaces:
            - 'Symfony\Component\EventDispatcher\EventSubscriberInterface'
            - 'Nette\Application\IPresenter'

Block comment should be used instead of one liner

 class SomeClass
 {
-    /** @var int */
+    /**
+     * @var int
+     */
     public $count;
 }

Use explicit and informative exception names over generic ones

โŒ

<?php

throw new RuntimeException('...');

๐Ÿ‘

<?php

throw new FileNotFoundException('...');

Class "X" cannot be parent class. Use composition over inheritance instead.

# ecs.yml
services:
    Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenParentClassSniff:
        forbiddenParentClasses:
            - 'Doctrine\ORM\EntityRepository'
            # again, you can use fnmatch() pattern
            - '*\AbstractController'

โŒ

<?php

use Doctrine\ORM\EntityRepository;

final class ProductRepository extends EntityRepository
{
}

๐Ÿ‘

<?php

use Doctrine\ORM\EntityRepository;

final class ProductRepository
{
    /**
     * @var EntityRepository
     */
    private $entityRepository;

    public function __construct(EntityRepository $entityRepository)
    {
        $this->entityRepository = $entityRepository;
    }
}

Use explicit return values over magic "&$variable" reference

โŒ

<?php

function someFunction(&$var)
{
    $var + 1;
}

๐Ÿ‘

<?php

function someFunction($var)
{
    return $var + 1;
}

Use services and constructor injection over static method

โŒ

<?php

class SomeClass
{
    public static function someFunction()
    {
    }
}

๐Ÿ‘

<?php

class SomeClass
{
    public function someFunction()
    {
    }
}

Constant should have docblock comment

class SomeClass
{
    private const EMPATH_LEVEL = 55;
}

๐Ÿ‘

<?php

class SomeClass
{
    /**
     * @var int
     */
    private const EMPATH_LEVEL = 55;
}

Use per line assign instead of multiple ones

โŒ

<?php

$value = $anotherValue = [];

๐Ÿ‘

<?php

$value = [];
$anotherValue = [];

Prefer sprintf() over multiple concats ( . ).

โŒ

<?php

return 'Class ' . $oldClass . ' was removed from ' . $file . '. Use ' . self::class . " instead';

๐Ÿ‘

<?php

return sprintf('Class "%s" was removed from "%s". Use "%s" instead', $oldClass, $file, self::class);

Is 2 . too strict? Just configure it:

# ecs.yml
services:
    Symplify\CodingStandard\Sniffs\ControlStructure\SprintfOverContactSniff:
        maxConcatCount: 4 # "3" by default

There should not be comments with valid code

โŒ

<?php

// $file = new File;
// $directory = new Diretory([$file]);

Debug functions should not be left in the code

โŒ

<?php

d($value);
dd($value);
dump($value);
var_dump($value);

Use service and constructor injection rather than instantiation with new

โŒ

<?php

class SomeController
{
   public function renderEdit(array $data)
   {
        $database = new Database;
        $database->save($data);
   }
}

๐Ÿ‘

<?php

class SomeController
{
   public function renderEdit(array $data)
   {
        $this->database->save($data);
   }
}

This checkers ignores by default some classes, see $allowedClasses property.

In case want to exclude more classes, you can configure it with class or pattern using fnmatch:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\DependencyInjection\NoClassInstantiationSniff:
        extraAllowedClasses:
            - 'PhpParser\Node\*'

Doctrine entities are skipped as well. You can disable that by:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\DependencyInjection\NoClassInstantiationSniff:
        includeEntities: true

Abstract class should have prefix "Abstract"

โŒ

<?php

abstract class SomeClass
{
}

๐Ÿ‘

<?php

abstract class AbstractSomeClass
{
}

Class should have suffix by parent class/interface

โŒ

<?php

class Some extends Command
{
}

๐Ÿ‘

<?php

class SomeCommand extends Command
{
}

This checker check few names by default. But if you need, you can configure it:

# ecs.yml
services:
    Symplify\CodingStandard\Sniffs\Naming\ClassNameSuffixByParentSniff:
        parentTypesToSuffixes:
            # defaults
            - 'Command'
            - 'Controller'
            - 'Repository'
            - 'Presenter'
            - 'Request'
            - 'Response'
            - 'EventSubscriber'
            - 'FixerInterface'
            - 'Sniff'
            - 'Exception'
            - 'Handler'

Or keep all defaults values by using extra_parent_types_to_suffixes:

# ecs.yml
services:
    Symplify\CodingStandard\Sniffs\Naming\ClassNameSuffixByParentSniff:
        extraParentTypesToSuffixes:
            - 'ProviderInterface'

It also covers Interface suffix as well, e.g EventSubscriber checks for EventSubscriberInterface as well.


Interface should have suffix "Interface"

โŒ

<?php

interface Some
{
}

๐Ÿ‘

<?php

interface SomeInterface
{
}

Trait should have suffix "Trait"

โŒ

<?php

trait Some
{
}

๐Ÿ‘

<?php

trait SomeTrait
{
}

Brave Checkers

Possible Unused Public Method

โŒ

<?php

class SomeClass
{
    public function usedMethod()
    {
    }

    public function unusedMethod()
    {
    }
}

$someObject = new SomeClass;
$someObject->usedMethod();

๐Ÿ‘

<?php

class SomeClass
{
    public function usedMethod()
    {
    }
}

$someObject = new SomeClass;
$someObject->usedMethod();

Contributing

Open an issue or send a pull-request to main repository.

codingstandard's People

Contributors

carusogabriel avatar dg avatar enumag avatar jankonas avatar michaljurecko avatar ondram avatar ostrolucky avatar tomasvotruba avatar vlastavesely avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.