色んなPHP CS Fixerの紹介

色んなPHP CS Fixer達を紹介します。

* [Symplify/CodingStandard](https://github.com/Symplify/CodingStandard)
* [object-calisthenics/phpcs-calisthenics-rules](https://github.com/Symplify/CodingStandard)
* [bmitch/Codor](https://github.com/bmitch/Codor)
* [Slamdunk/php-cs-fixer-extensions](https://github.com/Slamdunk/php-cs-fixer-extensions)
* [PedroTroller/PhpCSFixer-Custom-Fixers](https://github.com/PedroTroller/PhpCSFixer-Custom-Fixers)
* [kubawerlos/php-cs-fixer-custom-fixers](https://github.com/kubawerlos/php-cs-fixer-custom-fixers)

## [CodingStandard](https://github.com/Symplify/CodingStandard)

### Indexed PHP arrays should have 1 item per line

- class: [`Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer`](src/Fixer/ArrayNotation/StandaloneLineInMultilineArrayFixer.php)

```diff
-$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.

- class: [`Symplify\CodingStandard\Fixer\Commenting\RemoveEmptyDocBlockFixer`](src/Fixer/Commenting/RemoveEmptyDocBlockFixer.php)

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

### Block comment should only contain useful information about types

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\Commenting\RemoveUselessDocBlockFixer`](src/Fixer/Commenting/RemoveUselessDocBlockFixer.php)

```diff
 /**
- * @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**:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Commenting\RemoveUselessDocBlockFixer:
        useless_types: ['mixed', 'object'] # [] by default
```

### Block comment should not have 2 empty lines in a row

- class: [`Symplify\CodingStandard\Fixer\Commenting\RemoveSuperfluousDocBlockWhitespaceFixer`](src/Fixer/Commenting/RemoveSuperfluousDocBlockWhitespaceFixer.php)

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

### Include/Require should be followed by absolute path

- class: [`Symplify\CodingStandard\Fixer\ControlStructure\RequireFollowedByAbsolutePathFixer`](src/Fixer/ControlStructure/RequireFollowedByAbsolutePathFixer.php)

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

### Types should not be referenced via a fully/partially qualified name, but via a use statement

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer`](src/Fixer/Import/ImportNamespacedNameFixer.php)

```diff
 namespace SomeNamespace;

+use AnotherNamespace\AnotherType;

 class SomeClass
 {
     public function someMethod()
     {
-        return new \AnotherNamespace\AnotherType;
+        return new AnotherType;
     }
 }
```

This checker imports single name classes like `\Twig_Extension` or `\SplFileInfo` by default. But if you need, you can **configure it**:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer:
        allow_single_names: true # false by default
```

You can also configure to check `/** @var Namespaced\DocBlocks */` as well:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer:
        include_doc_blocks: true # false by default
```

And what about duplicate class name? They are uniquized by vendor name:

```php
<?php declare(strict_types=1);

namespace SomeNamespace;

use Nette\Utils\Finder as NetteFinder;
use Symfony\Finder\Finder;

class SomeClass
{
    public function create(NetteFinder $someClass)
    {
        return new Finder;
    }
}
```

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

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer`](src/Fixer/LineLength/LineLengthFixer.php)

```diff
 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**:

```yaml
# easy-coding-standard.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
```

### Magic PHP methods (`__*()`) should respect their casing form

- class: [`Symplify\CodingStandard\Fixer\Naming\MagicMethodsNamingFixer`](src/Fixer/Naming/MagicMethodsNamingFixer.php)

```diff
 class SomeClass
 {
-    public function __CONSTRUCT()
+    public function __construct()
     {
     }
 }
```

### Property name should match its key, if possible

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer`](src/Fixer/Naming/PropertyNameMatchingTypeFixer.php)

```diff
-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**:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
        extra_skipped_classes:
            - 'MyApp*' # accepts anything like fnmatch
```

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

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer`](src/Fixer/Php/ClassStringToClassConstantFixer.php)

```diff
-$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**:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer:
        class_must_exist: false # true by default
```

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

- class: [`Symplify\CodingStandard\Fixer\Property\ArrayPropertyDefaultValueFixer`](src/Fixer/Property/ArrayPropertyDefaultValueFixer.php)

```diff
 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

- class: [`Symplify\CodingStandard\Fixer\Strict\BlankLineAfterStrictTypesFixer`](src/Fixer/Strict/BlankLineAfterStrictTypesFixer.php)

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

### Non-abstract class that implements interface should be final

*Except for Doctrine entities, they cannot be final.*

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\Solid\FinalInterfaceFixer`](src/Fixer/Solid/FinalInterfaceFixer.php)

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

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

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\Solid\FinalInterfaceFixer:
        onlyInterfaces:
            - 'Symfony\Component\EventDispatcher\EventSubscriberInterface'
            - 'Nette\Application\IPresenter'
```

### Block comment should be used instead of one liner

- class: [`Symplify\CodingStandard\Fixer\Commenting\BlockPropertyCommentFixer`](src/Fixer/Commenting/BlockPropertyCommentFixer.php)

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

### Use explicit and informative exception names over generic ones

- class: [`Symplify\CodingStandard\Sniffs\Architecture\ExplicitExceptionSniff`](src/Sniffs/Architecture/ExplicitExceptionSniff.php)

:x:

```php
throw new RuntimeException('...');
```

:+1:

```php
throw new FileNotFoundException('...');
```

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

- class: [`Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenReferenceSniff`](src/Sniffs/CleanCode/ForbiddenReferenceSniff.php)

:x:

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

:+1:

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

### Use services and constructor injection over static method

- class: [`Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenStaticFunctionSniff`](src/Sniffs/CleanCode/ForbiddenStaticFunctionSniff.php)

:x:

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

:+1:

```php
class SomeClass
{
    public function someFunction()
    {
    }
}
```

### Constant should have docblock comment

- class: [`Symplify\CodingStandard\Sniffs\Commenting\VarConstantCommentSniff`](src/Sniffs/Commenting/VarConstantCommentSniff.php)

```php
class SomeClass
{
    private const EMPATH_LEVEL = 55;
}
```

:+1:

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

### Prefer `sprintf()` over multiple concats ( . ).

- :wrench:
- class: [`Symplify\CodingStandard\Sniffs\ControlStructure\SprintfOverContactSniff`](src/Sniffs/ControlStructure/SprintfOverContactSniff.php)

:x:

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

:+1:

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

Is 2 `.` too strict? Just configure it:

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Sniffs\ControlStructure\SprintfOverContactSniff:
        maxConcatCount: 4 # "3" by default
```

### There should not be comments with valid code

- class: [`Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff`](src/Sniffs/Debug/CommentedOutCodeSniff.php)

:x:

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

### Debug functions should not be left in the code

- class: [`Symplify\CodingStandard\Sniffs\Debug\DebugFunctionCallSniff`](src/Sniffs/Debug/DebugFunctionCallSniff.php)

:x:

```php
dump($value);
```

### Use service and constructor injection rather than instantiation with new

- :wrench:
- class: [`Symplify\CodingStandard\Sniffs\DependencyInjection\NoClassInstantiationSniff`](src/Sniffs/DependencyInjection/NoClassInstantiationSniff.php)

:x:

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

:+1:

```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`](http://php.net/manual/en/function.fnmatch.php):

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\DependencyInjection\NoClassInstantiationSniff:
        extraAllowedClasses:
            - 'PhpParser\Node\*'
```

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

```yaml
# easy-coding-standard.yml
services:
    Symplify\CodingStandard\Fixer\DependencyInjection\NoClassInstantiationSniff:
        includeEntities: true
```

### Abstract class should have prefix "Abstract"

- class: [`Symplify\CodingStandard\Sniffs\Naming\AbstractClassNameSniff`](src/Sniffs/Naming/AbstractClassNameSniff.php)

:x:

```php
abstract class SomeClass
{
}
```

:+1:

```php
abstract class AbstractSomeClass
{
}
```

### Class should have suffix by parent class/interface

- :wrench:
- class: [`Symplify\CodingStandard\Sniffs\Naming\ClassNameSuffixByParentSniff`](src/Sniffs/Naming/ClassNameSuffixByParentSniff.php)

:x:

```php
class Some extends Command
{
}
```

:+1:

```php
class SomeCommand extends Command
{
}
```

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

```yaml
# easy-coding-standard.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`:

```yaml
# easy-coding-standard.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"

- class: [`Symplify\CodingStandard\Sniffs\Naming\InterfaceNameSniff`](src/Sniffs/Naming/InterfaceNameSniff.php)

:x:

```php
interface Some
{
}
```

:+1:

```php
interface SomeInterface
{
}
```

### Trait should have suffix "Trait"

- class: [`Symplify\CodingStandard\Sniffs\Naming\TraitNameSniff`](src/Sniffs/Naming/TraitNameSniff.php)

:x:

```php
trait Some
{
}
```

:+1:

```php
trait SomeTrait
{
}
```

## Brave Checkers

### Possible Unused Public Method

- class: [`Symplify\CodingStandard\Sniffs\DeadCode\UnusedPublicMethodSniff`](src/Sniffs/DeadCode/UnusedPublicMethodSniff.php)

- **Requires ECS due *double run* feature**.

:x:

```php
class SomeClass
{
    public function usedMethod()
    {
    }

    public function unusedMethod()
    {
    }
}

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

:+1:

```php
class SomeClass
{
    public function usedMethod()
    {
    }
}

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

---


## [phpcs-calisthenics-rules](https://github.com/Symplify/CodingStandard)

### 1. [Only `X` Level of Indentation per Method](http://williamdurand.fr/2013/06/03/object-calisthenics/#1-only-one-level-of-indentation-per-method)

:x:

```php
foreach ($sniffGroups as $sniffGroup) {
    foreach ($sniffGroup as $sniffKey => $sniffClass) {
        if (! $sniffClass instanceof Sniff) {
            throw new InvalidClassTypeException;
        }
    }
}
```

:+1:

```php
foreach ($sniffGroups as $sniffGroup) {
    $this->ensureIsAllInstanceOf($sniffGroup, Sniff::class);
}

// ...
private function ensureIsAllInstanceOf(array $objects, string $type)
{
    // ...
}
```

#### Use Just This One?

```bash
--sniffs=ObjectCalisthenics.Metrics.MaxNestingLevel
```

```yml
# easy-coding-standard.yml
services:
    ObjectCalisthenics\Sniffs\Metrics\MaxNestingLevelSniff: ~
```

#### :wrench: Configurable

- [in CodeSniffer XML](/src/ObjectCalisthenics/ruleset.xml#L3-L8)
- [in EasyCodingStandard YAML](/config/object-calisthenics.yml#L12-L14)

---

### 2. [Do Not Use "else" Keyword](http://williamdurand.fr/2013/06/03/object-calisthenics/#2-dont-use-the-else-keyword)

:x:

```php
if ($status === self::DONE) {
    $this->finish();
} else {
    $this->advance();
}
```

:+1:

```php
if ($status === self::DONE) {
    $this->finish();
    return;
}

$this->advance();
```

#### Use Just This One?

```
--sniffs=ObjectCalisthenics.ControlStructures.NoElseSniff
```

```yml
# easy-coding-standard.yml
services:
    ObjectCalisthenics\Sniffs\ControlStructures\NoElseSniff: ~
```

---

### 5. [Use Only One Object Operator (`->`) per Line](http://williamdurand.fr/2013/06/03/object-calisthenics/#5-one-dot-per-line)

:x:

```php
$this->container->getBuilder()->addDefinition(SniffRunner::class);
```

:+1:

```php
$containerBuilder = $this->getContainerBuilder();
$containerBuilder->addDefinition(SniffRunner::class);
```

#### Use Just This One?

```bash
--sniffs=ObjectCalisthenics.CodeAnalysis.OneObjectOperatorPerLine
```

```yml
# easy-coding-standard.yml
services:
    ObjectCalisthenics\Sniffs\CodeAnalysis\OneObjectOperatorPerLineSniff: ~
```

#### :wrench: Configurable

- [in CodeSniffer XML](/src/ObjectCalisthenics/ruleset.xml#L13-L20)
- [in EasyCodingStandard YAML](/config/object-calisthenics.yml#L19-L23)

---

### 6. [Do not Abbreviate](http://williamdurand.fr/2013/06/03/object-calisthenics/#6-dont-abbreviate)

This is related to class, trait, interface, constant, function and variable names.

:x:

```php
class EM
{
    // ...
}
```

:+1:

```php
class EntityMailer
{
    // ...
}
```

#### Use Just This One?

```bash
--sniffs=ObjectCalisthenics.NamingConventions.ElementNameMinimalLength
```

```yml
# easy-coding-standard.yml
services:
    ObjectCalisthenics\Sniffs\NamingConventions\ElementNameMinimalLengthSniff: ~
```

#### :wrench: Configurable

- [in CodeSniffer XML](/src/ObjectCalisthenics/ruleset.xml#L22-L28)
- [in EasyCodingStandard YAML](/config/object-calisthenics.yml#L25-L28)

---

### 7. [Keep Your Classes Small](http://williamdurand.fr/2013/06/03/object-calisthenics/#7-keep-all-entities-small)

:x:

```php
class SimpleStartupController
{
    // 300 lines of code
}
```

:+1:

```php
class SimpleStartupController
{
    // 50 lines of code
}
```

:x:

```php
class SomeClass
{
    public function simpleLogic()
    {
        // 30 lines of code
    }
}
```

:+1:

```php
class SomeClass
{
    public function simpleLogic()
    {
        // 10 lines of code
    }
}
```

:x:

```php
class SomeClass
{
    // 20 properties
}
```

:+1:

```php
class SomeClass
{
    // 5 properties
}
```

:x:

```php
class SomeClass
{
    // 20 methods
}
```

:+1:

```php
class SomeClass
{
    // 5 methods
}
```


#### Use Just These Ones?

```bash
--sniffs=ObjectCalisthenics.Files.ClassTraitAndInterfaceLength,ObjectCalisthenics.Files.FunctionLengthSniff,ObjectCalisthenics.Metrics.MethodPerClassLimit,ObjectCalisthenics.Metrics.PropertyPerClassLimitSniff
```

```yml
# easy-coding-standard.yml
services:
    ObjectCalisthenics\Sniffs\Files\ClassTraitAndInterfaceLengthSniff: ~
    ObjectCalisthenics\Sniffs\Files\FunctionLengthSniff: ~
    ObjectCalisthenics\Sniffs\Metrics\MethodPerClassLimitSniff: ~
    ObjectCalisthenics\Sniffs\Metrics\PropertyPerClassLimitSniff: ~
```

#### :wrench: Configurable

- [in CodeSniffer XML](/src/ObjectCalisthenics/ruleset.xml#L30-L50)
- [in EasyCodingStandard YAML](/config/object-calisthenics.yml#L30-L38)

---

### 9. [Do not Use Getters and Setters](http://williamdurand.fr/2013/06/03/object-calisthenics/#9-no-getterssettersproperties)

This rules is partially related to [Domain Driven Design](https://github.com/dddinphp).

- Classes should not contain public properties.
- Method should [represent behavior](http://whitewashing.de/2012/08/22/building_an_object_model__no_setters_allowed.html), not set values.

:x:

```php
class ImmutableBankAccount
{
    public $currency = 'USD';
```
```php
    private $amount;

    public function setAmount(int $amount)
    {
        $this->amount = $amount;
    }
}
```

:+1:

```php
class ImmutableBankAccount
{
    private $currency = 'USD';
```
```php
    private $amount;

    public function withdrawAmount(int $withdrawnAmount)
    {
        $this->amount -= $withdrawnAmount;
    }
}
```

---

## [bmitch/Codor](https://github.com/bmitch/Codor)

### Codor.ControlStructures.NoElse ###
Does not allow for any `else` or `elseif` statements.

:x:
```php
if ($foo) {
    return 'bar';
} else {
    return 'baz';
}
```

:white_check_mark:
```php
if ($foo) {
    return 'bar';
}
return 'baz';
```

### Codor.Files.FunctionLength ###
Functions/methods must be no more than 20 lines.

:x:
```php
public function foo()
{
    // more than 20 lines
}
```

:white_check_mark:
```php
public function foo()
{
    // no more than 20 lines
}
```
### Codor.Files.FunctionParameter ###
Functions/methods must have no more than 3 parameters.

:x:
```php
public function foo($bar, $baz, $bop, $portugal)
{
    // 
}
```

:white_check_mark:
```php
public function foo($bar, $baz, $bop)
{
    // 
}
```
### Codor.Files.ReturnNull ###
Functions/methods must not return `null`.

:x:
```php
public function getAdapter($bar)
{
    if ($bar === 'baz') {
        return new BazAdapter;
    }
    return null;
}
```

:white_check_mark:
```php
public function getAdapter($bar)
{
    if ($bar === 'baz') {
        return new BazAdapter;
    }
    return NullAdapter;
}
```
### Codor.Files.MethodFlagParameter ###
Functions/methods cannot have parameters that default to a boolean.

:x:
```php
public function getCustomers($active = true)
{
    if ($active) {
        // Code to get customers from who are active
    }
    
    // Code to get all customers
}
```

:white_check_mark:
```php
public function getAllCustomers()
{    
    // Code to get all customers
}

public function getAllActiveCustomers()
{    
    // Code to get customers from who are active
}
```
### Codor.Classes.ClassLength ###
Classes must be no more than 200 lines.

:x:
```php
class ClassTooLong
{
    // More than 200 lines
}
```

:white_check_mark:
```php
class ClassNotTooLong
{
    // No more than 200 lines
}
```
### Codor.Classes.ConstructorLoop ###
Class constructors must not contain any loops.

:x:
```php
public function __construct()
{
    for($index = 1; $index < 100; $index++) {
        // foo
    }
}
```

:white_check_mark:
```php
public function __construct()
{
    $this->someMethod();
}

private function someMethod()
{
    for($index = 1; $index < 100; $index++) {
        // foo
    }
}

```
### Codor.Classes.Extends ###
Warns if a class extends another class. Goal is to promote composition over inheritance (https://en.wikipedia.org/wiki/Composition_over_inheritance).

:x:
```php
class GasolineCar extends Vehicle
{
    //
}

class GasolineVehicle extends Vehicle
{
    //
}
```

:white_check_mark:
```php
class Vehicle
{
    private $fuel;
    
    public function __construct(FuelInterface $fuel)
    {
        $this->fuel;    
    }
}

class Gasoline implements FuelInterface
{

}

$gasolineCar = new Vehicle($gasoline);
```
### Codor.Classes.FinalPrivate ###
Final classes should not contain protected methods or variables. Should use private instead.

:x:
```php
final class Foo 
{
    protected $baz;

    protected function bar()
    {
        //
    }
}
```

:white_check_mark:
```php
final class Foo 
{
    private $baz;

    private function bar()
    {
        //
    }
}
```
### Codor.Classes.PropertyDeclaration ###
Produces an error if your class uses undeclared member variables. Only warns if class extends another class. 

:x:
```php
class Foo 
{
    private function bar()
    {
        $this->baz = 13;
    }
}
```

:white_check_mark:
```php
class Foo 
{
    private $baz;
    
    private function bar()
    {
        $this->baz = 13;
    }
}
```
### Codor.Files.FunctionNameContainsAndOr ###
Functions/methods cannot contain "And" or "Or". This could be a sign of a function that does more than one thing.

:x:
```php
public function validateStringAndUpdateDatabase()
{
    // code to validate string
    // code to update database
}
```

:white_check_mark:
```php
public function validateString()
{
    // code to validate string
}

public function updateDatabase()
{
    // code to update database
}
```
### Codor.Files.IndentationLevel ###
Functions/methods cannot have more than 2 level of indentation.

:x:
```php
public function foo($collection)
{
    foreach ($collection as $bar) {
        foreach ($bar as $baz) {
            //
        }
    }
}
```

:white_check_mark:
```php
public function foo($collection)
{
    foreach ($collection as $bar) {
        $this->process($bar);
    }
}

private function process($bar)
{
    foreach ($bar as $baz) {
        //
    }
}
```
### Codor.ControlStructures.NestedIf ###
Nested if statements are not allowed.

:x:
```php
public function allowedToDrink($person)
{
    if ($person->age === 19) {
        if ($person->hasValidId()) {
            return true;
        }
    }
    
    return false;
}
```

:white_check_mark:
```php
public function allowedToDrink($person)
{
    if ($person->age !== 19) {
        return false;
    }
       
    if (! $person->hasValidId()) {
        return false;
    }
    
    return true;
}
```
### Codor.Syntax.NullCoalescing ###
Produces an error if a line contains a ternary operator that could be converted to a Null Coalescing operator.

:x:
```php
$username = isset($customer['name']) ? $customer['name'] : 'nobody';
```

:white_check_mark:
```php
$username = $customer['name'] ?? 'nobody';
```

### Codor.Syntax.LinesAfterMethod ###
Only allows for 1 line between functions/methods. Any more than 1 will produce an error.

:x:
```php
public function foo()
{
    //
}


public function bar()
{
    //
}
```

:white_check_mark:
```php
public function foo()
{
    //
}

public function bar()
{
    //
}
```

### Codor.TypeHints.MixedReturnType ###
Prevents you from having a `mixed` type returned in a doc block.

:x:
```php
/**
 * @return mixed
 */
public function foo()
{
    //
}
```

:white_check_mark:
```php
/**
 * @return string
 */
public function foo()
{
    //
}
```