composer

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!

O que é o Symfony Flex e como ele funciona

O Symfony é um dos frameworks mais utilizados na linguagem PHP. Ele possui grande importância no ecossistema, pois além da utilização direta do framework, diversas outras ferrramentas e até frameworks utilizam seus componentes como base de desenvolvimento. Mesmo com tanta relevância o Symfony não era tão falado na comunidade brasileira, porém com as novidades apresentadas nos últimos tempos ele voltou a ganhar bastante destaque. Inclusive, prova disso é o evento oficial da Symfony que aconteceu em São Paulo.

Desenvolvedor Symfony Full-Stack
Formação: Desenvolvedor Symfony Full-Stack
Nesta formação você aprenderá desenvolver aplicações PHP usando o framework Symfony com desenvoltura. Ao final desta formação, terá condições de trabalhar em grandes aplicações web ou APIs integradas com diversos serviços, tudo isso usando as melhores práticas do mercado.
CONHEÇA A FORMAÇÃO

Um dos recursos mais interessantes aprensentados pela equipe do Symfony é o Flex. Ele automatiza o processo de configuração das dependências no momento da instalação. Isso possibilita ao desenvolvedor começar o projeto com o mínimo possível de dependencias, algo parecido com um micro framework, e adicionar novas dependencias de forma muito fluida até chegar a uma estrutura parecida com um framework full stack.

O que é Symfony Flex

O Symfony Flex é um plugin para composer. Ele automatiza os principais processos na hora da criação do projeto e instalação das dependências. Pode ser usado a partir da versão 3.4 do Symfony e passou a ser usado por padrão a partir da versão 4. O Flex altera o comportamento padrão de alguns dos comandos do Composer para permitir a automatização das tarefas de gerenciamento do projeto.

Quando realizamos a instalação de um novo pacote do composer, o Symfony Flex verifica dentro de um repositório próprio se existe alguma automatização correspondente a essa dependência, se existir ele executa as ações definidas.

O que são Recipes

Recipe (receita) é o nome dado ao conjunto de arquivos responsável pela automatização do processo de instalação de uma dependência específica. As instruções são definidas dentro de um arquivo chamado manifest.json que fica dentro do repositório do Flex, veja um exemplo abaixo:

{
    "bundles": {
        "Symfony\Bundle\DebugBundle\DebugBundle": ["dev", "test"]
    },
    "copy-from-recipe": {
        "config/": "%CONFIG_DIR%/"
    }
}

O recipe acima está pedindo para adicionar um novo bundle no arquivo de configuração e copiar a pasta config de dentro do repositório do Symfony Flex para o projeto. Esse arquivo faz parte do recipe de debug https://github.com/symfony/recipes/blob/master/symfony/debug-bundle/4.1/manifest.json

Ao executar essas tarefas, o Flex evita que o desenvolvedor necessite executar manualmente, diminuindo a chance de erro e a complexidade de instalação de novos pacotes.

Symfony - Gerenciando aplicações com Symfony Flex
Curso de Symfony - Gerenciando aplicações com Symfony Flex
CONHEÇA O CURSO

Repositório de recipes

O Symfony Flex possui 2 repositórios de recipes. O primeiro é o repositório oficial onde somente projetos da equipe do Symfony são colocados:

O segundo é o repositório contrib onde qualquer pessoa pode submeter um recipe para automatizar as configurações do seu bundle.

Ainda é possível criar repositórios privados onde podemos colocar as recipes do Flex que serão usadas somente dentro dos nossos projetos.

Como o Flex cria a estrutura da aplicação Symfony na instalação

Symfony - Fundamentos
Curso de Symfony - Fundamentos
CONHEÇA O CURSO

Como instalar novas dependências no projeto

Uma vez que temos uma aplicação que utiliza o Flex podemos facilmente instalar novas dependências e se beneficiar das automatizações. O Symfony possui uma página onde podemos consultar todos os recipes tanto oficiais quanto do repositório de contrib https://flex.symfony.com, vamos procurar por twig:

Note que temos vários recipes relacionados ao twig. Vamos instalar o pacote symfony/twig-bundle.

composer require symfony/twig-bundle

Se tudo der certo o resultado final será parecido com esse:

Note que após instalar o pacote do composer no projeto ele executou o recipe. Ao fazer isso o Flex configurou todos os detalhes necessários para o Twig funcionar no seu projeto. Podemos ver isso na prática se olharmos no Git as alterações realizadas:

Apelidos para os pacotes do Flex

Alguns pacotes possuem Aliases (apelidos). Se notar o pacote que instalamos verá que ele possui alguns nomes definidos:

O principal objetivo do alias é facilitar na hora de instalação, podemos fazer simplesmente:

composer require twig

Ou

composer require template

Se estiver dentro de uma aplicação que não utiliza o Flex, o composer não vai encontrar esses pacotes, pois o padrão para identificação de pacotes do composer é nome-vendor/nome-pacote. Usar apelidos só é possível graças ao Symfony Flex e em pacotes que possuem Recipes.

Symfony -  Formulários e Validações
Curso de Symfony - Formulários e Validações
CONHEÇA O CURSO

Prefetch e download simultâneo

Quando usamos o Flex ele adiciona 2 funções muito interessantes ao composer:

  • Prefetch – Ele baixa todos os pacotes necessários antes de iniciar a instalação
  • Download Simultâneo – O composer por padrão baixa uma dependência por vez, com uso do Flex ele passar a realizar o download ao mesmo tempo de vários pacotes, tornando mais rápido o processo.

O interessante é que se instalarmos o Flex globalmente no sistema operacional esses 2 recursos passam a ser usados em qualquer projeto, mesmo que não utilize o Symfony. Para instalar o Flex global basta executar:

composer global require symfony/flex 

Conclusão

O Flex torna o gerenciamento das dependências de uma aplicação muito mais simples, rápido e seguro. Uma vez que remove a necessidade de configuração manual por parte do desenvolvedor. Além disso ele ainda conta com uma série de recursos avançados que facilitam o trabalho diário de manutenção de aplicações Symfony.