PHP PSRs : PSR-2 & PSR-12 Parte 1
Tags: php, braziliandevs
Published: 2023-10-07 01:09:59

## PSR-2 (CODING STYLE GUIDE)

A PSR-2 surgiu com o objetivo de tornar a escrita e a legibilidade do código mais simples e fácil para os desenvolvedores.

> **INFORMAÇÃO IMPORTANTE**
A PSR-2 foi **descontinuada/substituda** pela PSR-12 devido a inúmeras funcionalidades que foram surgindo no PHP.

## PSR-12 (EXTENDED CODING STYLE)

A PSR-12 é uma extensão da PSR-2 e possui o mesmo objetivo que ela, porém com um contexto mais moderno e novas funcionalidades que seguem a evolução do PHP.

Como o PHP 7 teve muitas mudanças, a reescrita da PSR-2 em uma nova PSR foi necessária para atender a todas as novidades disponíveis no PHP 7.

## Regras

- **Regra 1:**

Os códigos PHP **DEVEM** seguir os padrões estabelecidos na
PSR-1. Por ser uma extensão da PSR-1, seu código primeiramente deve estar em conformidade com a PSR-1 antes de aplicar a PSR-12.

O termo _StudlyCaps_ no PSR-1 **DEVE** ser interpretado como _PascalCase_ , onde a primeira letra de cada palavra é maiúscula.

- **Regra 2:**

Arquivos PHP **DEVEM** possuir o padrão UNIX de terminação de linha.

- **CRLF:** retorno de carro + avanço de linha, Unicode caracteres D + 000A 000
- **LF:** alimentação de linha, caracteres Unicode 000A
- **NEL:** próxima linha, o caractere Unicode 0085
- **LS:** separador de linha, caractere Unicode 2028
- **PS:** separador de parágrafo, caractere Unicode 2029

O padrão UNIX adotado pela PSR-12 é o **LF**. Geralmente, as IDEs já vêm configuradas para o padrão UNIX, mas isso pode ser alterado facilmente dependendo da IDE utilizada.


- **Regra 3:**

Arquivos contendo apenas código PHP **DEVEM** possuir uma linha em branco ao final. Após toda a lógica aplicada, deve haver uma linha em branco ao final do arquivo.

- **Regra 4:**

Arquivos contendo **apenas** PHP **DEVEM** ter a TAG de fechamento omitida. A regra não se aplica aos arquivos contendo HTML + PHP.

- **Regra 5:**

O comprimento máximo de uma linha de código **DEVE** ser de 120 caracteres. Verificadores de estilo automatizado **DEVEM** avisar, mas **NÃO DEVEM** exibir erro.

As linhas de código **NÃO DEVEM** ter mais de 80 caracteres. Linhas de código mais longas **DEVEM** ser quebradas em várias linhas subsequentes de no máximo 80 caracteres.

Portanto, atente-se para que a cada 80 caracteres você possa quebrar a linha de modo que fique legível e, caso não consiga, você ainda possui o limite de 120 caracteres.

- **Regra 6:**

Linhas que possuem conteúdo **NÃO DEVEM** possuir espaços em branco ao final de seu conteúdo.

- **Regra 7:**

Para facilitar a interpretação do código, linhas em branco **PODEM** ser adicionadas. Você pode adicionar linhas em branco para tornar a interpretação do código mais fácil.

```php
<?php

    class Usuario
    {

      private $nome;

      private $idade;

      private $sexo;

      public function __construct($nome, $idade, $sexo)
      {
      }

    }
// linha em branco no final do código
```

- **Regra 8:**

**NÃO DEVE** haver múltiplas declarações em uma única linha cada declaração de variável deve ser feita em uma nova linha.

Maneira certa:

```php
<?php

    $nome = 'Jhones';
    
    $sobrenome = 'S. Clementino';
```
Maneira errada:

```php
<?php

    $nome = 'Jhones'; $sobrenome = 'S. Clementino';
```

- **Regra 9:**

Códigos PHP **DEVEM** possuir indentação com 4 espaços e não com TABs. Algumas IDEs já vêm com o padrão de 4 espaços ao teclar o TAB.

- **Regra 10:**

As palavras-chaves, tipos reservados e constantes true, false e null **DEVEM** ser escritas com letras minúsculas.

Quaisquer novos tipos e palavras-chaves adicionados em versões futuras do PHP **DEVEM** estar em minúsculas.

É necessário usar uma forma abreviada de palavras-chaves do
tipo de dado, ou seja, bool em vez de boolean, int em vez de
integer etc.

- **Regra 11:**

Se o cabeçalho estiver presente, cada um dos blocos a seguir **DEVE** ser separado por uma única linha em branco e **NÃO DEVE** conter uma linha em branco.

Cada bloco **DEVE** estar na ordem listada a seguir, mas os blocos que não são relevantes podem ser omitidos.

- Tag de abertura <?php do PHP;
- Docblock /** Descrição */ no nível do arquivo;
- Uma ou mais declarações declare() ;
- A definição do namespace do arquivo;
- Uma ou mais instruções de importação use baseadas em
classes;
- Uma ou mais instruções de importação use baseadas em funções;
- Uma ou mais instruções de importação use baseadas em constantes;
- O restante do código.

Vamos conferir um exemplo a seguir que ilustra a aplicação da sequência definida pela PSR-12 citada anteriormente:

```php
<?php

    /**
     * Descrição do arquivo
     */

    declare(strict_types=1);

    namespace App\Controller\Usuario;

    use App\Controller\{AbstractController as Abc, ControllerInterface, BaseController as Base};
    use App\Entity\Usuario;

    use function App\Functions\{functionA, functionN, functionC};
    use function App\Repository\Functions\insert;

    use const App\Controller\{RESPONSE_JSON, RESPONSE_XML, RESPONSE_ERROR};
    use const App\Service\{CONSTANT_A}

    /**
     * Classe de exemplo
     */
    class UsuarioController
    {
      //Código...
    }

```

- **Regra 12:**

Os namespaces compostos com profundidade superior a dois **NÃO DEVEM** ser utilizados.

O exemplo a seguir demonstra a utilização máxima de composição permitida:

```php
<?php

    use App\Service\{
        Usuario\UsuarioService,
        Contato\ContatoService,
        ServiceAbstract,
    }

```

O exemplo a seguir não é **permitido** pela PSR-12:

```php
<?php

    use App\Service\{
        Usuario\Admin\UsuarioService,
        Contato\ContatoService,
        ServiceAbstract,
    }

```

- **Regra 13:**

Se desejar declarar tipos estritos em arquivos contendo marcação HTML fora das TAGs de abertura <?php e fechamento ?> do PHP, a declaração **DEVE** estar na primeira linha do arquivo e incluir uma TAG de abertura <?php do PHP, a declaração de tipos estritos e em seguida TAG de fechamento ?> do PHP.

```php
<?php declare(strict_types=1) ?>
<html>
<body>
    <?php //Código PHP... ?>
</body>
</html>
```
Instruções declare() **NÃO DEVEM** conter espaços e **DEVEM** ser declaradas exatamente da maneira a seguir: declare(strict_types=1). O ponto e vírgula no final da instrução é opcional.

- **Regra 14:**

As declarações de bloco declare contendo o código a ser executado são permitidas e **DEVEM** ser formatadas como demonstrado no exemplo a seguir. Observe a posição das chaves e o espaçamento:

```php
<?php

    declare(ticks=1) {
      // código...
    }

```

- **Regra 15:**

Após qualquer chave de fechamento, **NÃO DEVE** haver nenhum comentário ou declaração na mesma linha.

Ao instanciar uma nova classe, os parênteses **DEVEM** estar
sempre presentes, mesmo quando não houver parâmetros
passados para o construtor.

```php
<?php

    new Usuario();

```

- **Regra 16:**

As palavras-chaves extends e implements **DEVEM** ser declaradas na mesma linha que contém o nome da classe.

A chave de abertura { da classe **DEVE** ser inserida em uma
nova linha e **NÃO DEVE** ser precedida ou seguida por uma linha em branco.

A chave de fechamento } da classe também **DEVE** ser inserida em uma nova linha logo após a definição do corpo da
classe e **NÃO DEVE** ser precedida ou seguida por uma linha em branco.

```php
<?php

    class UsuarioController extends ControllerAbstract implements Countable
    {
      //Definição do corpo da classe...
    }
```

- **Regra 17:**

Quando houver a necessidade de múltiplos implements , eles **PODEM** ser divididos em múltiplas linhas, sendo que cada linha subsequente é recuada uma veze **DEVE** possuir somente uma interface por linha.

```php
<?php

    class UsuarioController extends ControllerAbstract implements 
       \Countable,
       \Serializable
    {
      //Definição do corpo da classe...
    }
```

- **Regra 18:**

Para utilizar Traits e usufruir da herança vertical dentro das classes, a instrução use **DEVE** ser declarada na próxima linha após a chave { de abertura da classe.

```php
<?php

    namespace App\Controller\Usuario;

    use App\Usuario\UsuarioTrait;

    class UsuarioController
    {
      use UsuarioTrait;
    }

```
- **Regra 19:**

Cada Trait a ser utilizada dentro da classe **DEVE** ser incluída uma por linha, sendo que cada Trait **DEVE** ter a sua própria declaração de uso use.

```php
<?php

    namespace App\Controller\Usuario;

    use App\Usuario\UsuarioTrait;
    use App\Contato\ContatoTrait;
    use App\Endereco\EnderecoTrait;

    class UsuarioController
    {
      use UsuarioTrait;
      use ContatoTrait;
      use EnderecoTrait;
    }

```

- **Regra 20:**

Quando a classe não tem nada após a declaração de uso use, a chave de fechamento da classe **DEVE** estar na linha subsequente.

Se a classe tiver conteúdo após a declaração de uso da Trait **DEVE** ter uma linha em branco após a declaração de uso use.

```php
<?php

    namespace App\Controller\Usuario;

    use App\Usuario\UsuarioTrait;

    class UsuarioController
    {
      use UsuarioTrait;
    
      private $usuario;
    }

```

- **Regra 21:**

O uso dos operadores _insteadof_ e _as_ **DEVE** ser feito da seguinte maneira, percebendo recuo, espaçamento e novas linhas:

```php
<?php

    namespace App\Controller\Usuario;

    use App\Usuario\UsuarioTrait;
    use App\Contato\ContatoTrait;
    use App\Endereco\EnderecoTrait;

    class UsuarioController
    {
      use A, B, C {
          B::getUsuario insteadof A;
          A::getContato insteadof B;
          C::getEndereco as Endereco;
      }
    }

```

- **Regra 22:**

A visibilidade ou modificadores de acesso **DEVEM** ser definidos em todas as propriedades. Toda propriedade que for definida deve possuir o modificador de acesso definido antes do seu nome.

```php
<?php

    class Usuario
    {
      private $nome;
      protected static $sexo;
      public int $indade;
    }

```

- **Regra 23:**

A palavra-chave var **NÃO DEVE** ser utilizada para a definição de propriedades da classe.

```php
<?php

    class Usuario
    {
      var $nome;
      var $sobrenome;
      var $sexo;
      var $idade;
    }

```

Apesar de não ser correto, o código será interpretado corretamente, e automaticamente todas as propriedades assumirão a visibilidade pública.