Ferramentas essenciais para um projeto PHP

Este será um artigo um pouco diferente dos últimos que tenho escrito, vou citar as quatro principais ferramentas que considero essenciais para qualquer projeto PHP:

  • PHPUnit (Testes unitários);
  • PHPStan (Analisador estático);
  • PHP-CS-Fixer (Corrige estilo de código);
  • PHP Insights (Analisa o estilo e a qualidade do código);
Desenvolvedor PHP Sênior
Formação: Desenvolvedor PHP Sênior
Nesta formação você aprenderá aspectos avançados da linguagem PHP e de seu ecossistema, conhecimentos essenciais para se tornar um desenvolvedor diferenciado, e com isso, você terá conhecimento para desenvolver aplicações PHP usando as práticas mais modernas do mercado.
CONHEÇA A FORMAÇÃO

1) PHPUnit

O PHPUnit é o principal e mais estabelecido framework para testes unitários em PHP. Automatizar testes é um requisito cada vez mais essencial para os projetos, não importando se você vai seguir TDD como metodologia, mas pelo menos testar as partes mais críticas da aplicação é algo que pode te salvar algumas boas horas procurando bugs e corrigindo problemas da evolução natural do software.

Você pode instalá-lo em seu projeto executando:

$ composer require phpunit/phpunit:^8.0 --dev

Hoje a ferramenta já tem a documentação traduzida para o português, você pode ler aqui.

Testar no PHPUnit é super simples e bem parecido com a forma que se faz em outros frameworks de teste de outras linguagens:

Exemplo extraído da documentação:

<?php

declare(strict_types=1);

final class Email
{
    private $email;

    private function __construct(string $email)
    {
        $this->ensureIsValidEmail($email);

        $this->email = $email;
    }

    public static function fromString(string $email): self
    {
        return new self($email);
    }

    public function __toString(): string
    {
        return $this->email;
    }

    private function ensureIsValidEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                sprintf(
                    '"%s" is not a valid email address',
                    $email
                )
            );
        }
    }
}

Essa classe poder ser facilmente testada:

<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

final class EmailTest extends TestCase
{
    public function testCanBeCreatedFromValidEmailAddress(): void
    {
        $this->assertInstanceOf(
            Email::class,
            Email::fromString('user@example.com')
        );
    }

    public function testCannotBeCreatedFromInvalidEmailAddress(): void
    {
        $this->expectException(InvalidArgumentException::class);

        Email::fromString('invalid');
    }

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user@example.com',
            Email::fromString('user@example.com')
        );
    }
}
PHP - Testes unitários com PHPUnit
Curso de PHP - Testes unitários com PHPUnit
CONHEÇA O CURSO

2) PHPStan

O PHPStan é um analisador estático que varre o código da sua aplicação procurando por erros e incongruências sem que haja a necessidade de executá-lo, a análise é toda estática.

É uma ferramenta essencial para te apontar bugs ou erros que certamente aparecerão em algum momento do uso da aplicação.

Para instalar o PHPStan no seu projeto:

$ composer require --dev phpstan/phpstan

Uma vez instalado, basta executar a ferramenta indicando quais pastas ele deve avaliar:

$ ./vendor/bin/phpstan analyse src tests

Nesse caso, estará avaliando as pastas src e tests.

Você ainda pode especificar o quão estrita você quer que a análise seja feita. Por padrão ele opera no level 0, mas vai até o 7:

$ ./vendor/bin/phpstan analyse src tests --level 7

Para aplicações que rodam em cima do Laravel, tem o Larastan, que facilita a instalação e personalização.

Apesar de eu preferir o PHPStan, também existe o ótimo Psalm, mantido pelo pessoal do Vimeo. Vale a pena estudá-lo, talvez você venha a preferi-lo.

3) PHP-CS-Fixer

O PHP-CS-Fixer corrige todo o estilo do seu código, quebras, espaços, estilo de declarações etc. É possível definir para que ele siga as PSR-1 e PSR-2, por exemplo. Não obstante, já estão desenvolvendo suporte nele para o mais novo padrão de estilo de código, o PSR-12.

Para instalá-lo em seu projeto:

$ composer require friendsofphp/php-cs-fixer --dev

E para rodar as correções usando as regras da PSR-2:

./vendor/bin/php-cs-fixer fix src --rules=@PSR2 --allow-risky yes

Nesse caso ele rodará na pasta src.

Uma forma mais simples de configurar o perfil de execução dele é criando um arquivo .php_cs na raiz do seu projeto e então definir o que é pra ele validar, o que não é, quais regras usar, quais configurações de estilo usar etc. Em nossas aplicações no TreinaWeb usamos esse perfil:

<?php

$finder = Symfony\Component\Finder\Finder::create()
    ->notPath('vendor')
    ->notPath('bootstrap')
    ->notPath('storage')
    ->notPath('resources')
    ->in(__DIR__)
    ->name('*.php')
    ->notName('*.blade.php');

return PhpCsFixer\Config::create()
    ->setRules([
        '@PSR2' => true,
        'final_class' => true,
        'static_lambda' => true,
        'linebreak_after_opening_tag' => true,
        'blank_line_after_opening_tag' => true,
        'declare_strict_types' => true,
        'array_syntax' => ['syntax' => 'short'],
        'ordered_imports' => ['sortAlgorithm' => 'length'],
        'no_unused_imports' => true,
        'native_function_invocation' => true,
        'is_null' => true,
        'list_syntax' => [
            'syntax' => 'short',
        ],
        'lowercase_cast' => true,
        'lowercase_static_reference' => true,
        'mb_str_functions' => true,
        'modernize_types_casting' => true,
        'native_constant_invocation' => true,
        'native_function_casing' => true,
        'new_with_braces' => true,
        'blank_line_before_statement' => [
            'statements' => ['declare',],
        ],
        'return_type_declaration' => [
            'space_before' => 'none',
        ],
    ])
    ->setFinder($finder);

Outras configurações você pode verificar no repositório oficial da ferramenta. Uma vez tendo o arquivo .php_cs, é só executar sem precisar informar --rules:

./vendor/bin/php-cs-fixer fix src --allow-risky yes

4) PHP Insights

Ferramenta para análise da qualidade do código. Ele divide a análise em quatro categorias: código, complexidade (complexidade ciclomática etc), arquitetura (tamanho de métodos e classes, entre outras análises) e estilo de código (formatação, padronização).

Para instalar a ferramenta no seu projeto:

$ composer require nunomaduro/phpinsights --dev

Depois, basta executar:

$ ./vendor/bin/phpinsights

Você pode criar um arquivo phpinsights.php na raiz do seu projeto para configurar o perfil da análise, ou seja, para definir o que você quer remover da análise, o que quer incluir etc. Por exemplo:

<?php

declare(strict_types=1);

use ObjectCalisthenics\Sniffs\Files\FunctionLengthSniff;
use NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits;
use ObjectCalisthenics\Sniffs\Metrics\MethodPerClassLimitSniff;
use SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff;
use NunoMaduro\PhpInsights\Domain\Insights\CyclomaticComplexityIsHigh;
use SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff;
use NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustBeValid;
use SlevomatCodingStandard\Sniffs\Namespaces\AlphabeticallySortedUsesSniff;
use PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff;
use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff;

return [
    'preset' => 'default',

    'exclude' => [
        'vendor',
        'config',
        'bootstrap',
        'resources',
        'storage',
        'public',
        'tests',
    ],

    'add' => [

    ],

    'remove' => [
        ForbiddenTraits::class,
        TypeHintDeclarationSniff::class,
        DisallowMixedTypeHintSniff::class,
        ComposerMustBeValid::class,
        AlphabeticallySortedUsesSniff::class,
        CamelCapsMethodNameSniff::class,
        LineLengthSniff::class,
    ],

    'config' => [
        CyclomaticComplexityIsHigh::class => [
            'maxComplexity' => 7,
        ],

        FunctionLengthSniff::class => [
            'maxLength' => 30,
        ],

        MethodPerClassLimitSniff::class => [
            'maxCount' => 12,
        ],
    ],
];

Maiores informações sobre a configuração da ferramenta, você pode ver no site oficial.

Usando o Composer como atalho para a execução de scripts

Por fim, uma coisa que acho bem útil e que uso bastante é colocar no composer.json atalhos para os scripts de linha de comando que mais executo no projeto. É possível defini-los numa área scripts, por exemplo:

    "scripts": {
        "phpunit": [
            "./vendor/bin/phpunit"
        ],        
        "cs": [
            "./vendor/bin/php-cs-fixer fix --allow-risky yes"
        ],
        "phpstan": [
            "./vendor/bin/phpstan analyse src tests --level 7"
        ],
        "phpinsights": [
            "./vendor/bin/phpinsights"
        ]
    },

Então, ao invés de executar ./vendor/bin/phpstan analyse src tests --level 7 eu apenas faço:

$ composer phpstan

O mesmo vale para a correção do estilo do código, apenas executo:

$ composer cs

Concluindo

Espero que o artigo tenha despertado a sua curiosidade. Recomendo demais que você leia a documentação dessas ferramentas e passe a utilizá-las, em pouco tempo você estará “viciado” e certamente as usará em todos os futuros projetos.

Até a próxima!

Deixe seu comentário

Head de desenvolvimento. Vasta experiência em desenvolvimento Web com foco em PHP. Graduado em Sistemas de Informação. Pós-graduando em Arquitetura de Software Distribuído pela PUC Minas. Zend Certified Engineer (ZCE) e Coffee Addicted Person (CAP). @KennedyTedesco