# PHP Style Guide

### How To Check and Repair PSR-2 Compliance

PSR-2 is a set of coding standards for PHP that the Orchard codebase must comply with: [PSR-2 Coding Style Guide](http://www.php-fig.org/psr/psr-2/)

Please pay attention to all details. Everything that's labeled "MUST" or "MUST NOT" are required to be fixed. Everything else that's labeled "SHOULD" or "SHOULD NOT" are not required to be fixed. Some small details are easily missed and there is a few bells and whistles that are not explicitly outlined but commonly applied by open source projects.

### Using PHP Code Sniffer

[PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer) is a tool that detects PSR-2 violations:

This is the command line syntax for checking a file \(or directory of files\):

```text
vendor/bin/phpcs -p --standard=PSR2 path/to/file.php
```

This is the production build report for PSR-2 compliance on Orchard using the PHP Code Sniffer: [Orchard Master Build](http://jeeves.theorchard.com:8080/job/Orchard-Master/violations/)

### Using the PHP Coding Standards Fixer \(from the sniffer\)

This is the syntax for converting a file \(or directory of files\):

```text
vendor/bin/phpcbf -n --standard=PSR2 --no-patch path/to/file.php
```

### Looking at the Changes on GitHub

Reviewing a PSR-2 formatting PR is an exercise in sanity-checking. Scan the changes using Github's ?w=1 url parameter to produce a reasonably readable display, then scan the changes looking for anything out of the ordinary. Usually a PSR-2 pull request will consist mainly of light red and light green, with a scattering of darker green \(usually converting NULL to null or other similarly easy to scan changes\).

### Unofficially Implied PSR-2 Rules

I've come across quite a few of these rules that are not stated by the PSR-2 style guide. Here is a list of them to share with you. Please ask any questions if there's other cases that are not covered here. BTW, PhpStorm can handle all rules outlined below that the phpcbf is not applying at the moment.

#### Control Structures

There's no explicit rules specified when there's multiple conditions in control structures that breaks the 120 character soft line length limit. Although it's not required to fix it, yet it can make the code more readable.

For example:

```text
if ($a == $b && ($c == $d || $e == $f) && $g == $h) {
    // do something
} else {
    // do nothing
}
```

The proper way to wrap the conditions in the if statement is this:

```text
if ($a == $b
    && ($c == $d || $e == $f)
    && $g == $h
) {
    // do something
} else {
    // do nothing
}
```

Here this rule has been applied:

> Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.
>
> When the argument list is split across multiple lines, the closing parenthesis and opening brace MUST be placed together on their own line with one space between them.

You can go even further and make the above code look like this:

```text
if ($a == $b
    && ($c == $d
        || $e == $f
    )
    && $g == $h
) {
    // do something
} else {
    // do nothing
}
```

#### Method Chaining

There's no mentioning at all about how to wrap long chains when method chaining exists. For instance:

```text
$foo = $bar->a->b->c->d->e->f->g->h;
```

If that line exceeds 120 character, phpcs will issue a warning. You don't have to fix it. But if you do, this is how it should look like.

```text
$foo = $bar->a
           ->b
           ->c
           ->d
           ->e
           ->f
           ->g
           ->h;
```

#### Arrays

Rule for wrapping array elements. Again, the same wrapping rule for method arguments is applied implicitly. Example:

```text
$foo = array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd', 4 => 'e', 5 => 'f', 6 => 'g', 7 => 'h');
```

is turned into:

```text
$foo = array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
    3 => 'd',
    4 => 'e',
    5 => 'f',
    6 => 'g',
    7 => 'h',
);
```

Short array example:

```text
$var = ['a' => 1, 'b' => ['c' => 2, 'd' => 3]];
```

```text
$var = [
    'a' => 1,
    'b' => [
        'c' => 2,
        'd' => 3,
    ],
];
```

If you have noticed the comma after the last element in the array shows up in the multi-line arrays above, the reason for that is actually stated on PHP's official site - [Arrays](http://php.net/manual/en/language.types.array.php).

> The comma after the last array element is optional and can be omitted. This is usually done for single-line arrays, i.e. array\(1, 2\) is preferred over array\(1, 2, \). For multi-line arrays on the other hand the trailing comma is commonly used, as it allows easier addition of new elements at the end.

#### Assignment Statements

Last if not least, consecutive assignment statements should be aligned using the equals sign. For example:

```text
$var1         = 'abc';
$varNumberTwo = 'efg';
```

This is also work-in-progress by the cs fixer guys. It's expected to be in the next release.

## Documentation

We document our code with phpdoc strings.

### Class Variables

Do:

```text
/**
 * Describe the variable here.
 * @var string
 */
protected $aString

/**
 * Describe this variable here.
 * @var array
 */
protected $anArray
```

### Functions

Do:

```text
class MyClass
{
    /**
     * Here goes my description of bar.
     * It returns a string and throws an exception when Foo is empty.
     *
     * @param string $foo Foo is a required param
     * @param int $foo2 Foo2 is optional
     *
     * @return string
     * @throws Exception if argument is not valid
     */
    function bar($foo, $foo2 = null)
    {
        if (empty($foo)) {
            throw new Exception('Foo is empty.');
        }

        return $foo . ' is bar';
    }
}
```

### Working with Legacy Code

Parts of our legacy code cannot be linted \(such as our `phtml` templates\). They are the source of many style inconsistencies and can be difficult to work with \( for instance, the file uses tabs instead of spaces\).

#### General Rule

Your code is going to be reviewed, so always look for the simplest implementation of the problem you are trying to solve. Sometimes, it means following the styles of the file \(for instance: using tabs instead of spaces to make it easier to read\).

If you are not in a rush, issue an initial pull request that will replace all the tabs with spaces.

#### Readable Content

Workstation is translated in several languages. Whenever you work with strings that are going to be displayed to users, make sure you tag them properly so our systems can extract and translate them appropriately.

Three implementations are possible depending on which template you work in.

```php
// Do:
<?=$this->translate('String to Translate')?>

// Deprecated syntax:
<?=$this->_translate->_('String to Translate')?>
<?=$this->translate->_('String to Translate')?>
```

#### Alternative syntax for control structures

Our phtml/php files contain many different ways to write control structures. Moving forward, we will follow:

Do:

```php
<?php if ($var) { ?>
    <span><hr></span>
<?php } else { ?>
    <hr>
<?php } ?>
```

We do not use: `if: endif;`, so don't:

```php
<?php if ($var): ?>
    <span><hr></span>
<?php endif; ?>

<?php if ($var): ?><hr><?php endif; ?>
```

## Other Things

### Single Quotes vs Double Quotes

We do not use double quotes. We only use single quotes.

Do:

```php
$myName = 'Fred';
```

Don't:

```php
$myName = "Fred";
```

### New Lines

New lines should be specified using the PHP constant `PHP_EOL`. They should not be specified using `\n`.

Do:

```php
echo 'Be cool' . PHP_EOL . 'Stay in school.';
```

Don't:

```php
echo "Be cool\nStay in school.";
```

