← Voltar ao blog

Coding standard do Magento 2 com PHPCS: setup e uso

Rodrigo Biazzi

Todo time concorda que o código deve seguir um padrão. Poucos times o impõem. No Magento o padrão já existe, vem com o projeto como dependência de dev e tem verificações que vão além de formatação: saída sem escaping em templates, funções PHP desencorajadas, SQL puro e mais. Rodar é barato. Não rodar significa que esses achados aparecem depois, em um review do Marketplace, em uma auditoria de segurança ou em produção.

Este artigo mostra como configurar o coding standard do Magento com o PHP_CodeSniffer, ajustá-lo para um projeto e rodá-lo de um jeito que as pessoas não passem a ignorar.

O que é o coding standard do Magento

O padrão é distribuído como o pacote Composer magento/magento-coding-standard. Ele fornece um ruleset do PHP_CodeSniffer chamado Magento2, que se baseia no PSR-12 e adiciona sniffs específicos do Magento. Ele também puxa o PHPCompatibility, que verifica se o código roda nas versões de PHP que você mira, e inclui a configuração do ESLint para JavaScript.

Algumas das verificações que mais importam na prática:

  • Escaping em templates. O sniff de XSS em templates aponta saídas em arquivos .phtml que não passam por um método de escaper.
  • Funções desencorajadas. Chamadas como file_get_contents, serialize ou curl_init, onde o Magento tem alternativas do framework, como os drivers de filesystem, o serializer e o client HTTP.
  • SQL puro. SQL escrito como string em vez de usar o select builder.
  • Language constructs. exit, die e crases em código de aplicação.
  • Padrões legados. Scripts de instalação antigos, classes deprecated e restos parecidos.

Isso não é preferência de estilo. Várias dessas verificações apontam direto para problemas de segurança e de manutenção.

Instalação

Primeiro confira se já está lá:

vendor/bin/phpcs -i

Se a saída listar Magento2, está pronto. Se não, faça o require do pacote e registre o caminho dele no PHPCS:

composer require --dev magento/magento-coding-standard
vendor/bin/phpcs --config-set installed_paths ../../magento/magento-coding-standard/,../../phpcompatibility/php-compatibility

O próprio composer.json do pacote tem scripts que definem esse caminho depois da instalação. Se eles não rodaram, por exemplo porque os scripts foram desabilitados, o comando manual acima faz a mesma coisa. Os caminhos relativos são resolvidos a partir da pasta de instalação do PHPCS dentro de vendor.

Um ruleset de projeto

Passar --standard=Magento2 em todo comando funciona, mas um phpcs.xml.dist na raiz do projeto é mais fácil de compartilhar e permite definir caminhos, extensões de arquivo e exclusões uma vez só:

<?xml version="1.0"?>
<ruleset name="Project">
    <description>Coding standard for custom code</description>

    <file>app/code</file>
    <file>app/design</file>

    <arg name="extensions" value="php,phtml"/>
    <arg name="colors"/>
    <arg value="sp"/>

    <exclude-pattern>*/node_modules/*</exclude-pattern>
    <exclude-pattern>*/web/css/source/_module.less</exclude-pattern>

    <rule ref="Magento2"/>

    <config name="testVersion" value="8.3-"/>
</ruleset>

Com esse arquivo no lugar, rodar vendor/bin/phpcs sem argumentos verifica o seu código com as suas configurações. Os desenvolvedores podem manter um phpcs.xml local, que o PHPCS prefere ao arquivo dist, sem alterar o compartilhado.

O valor testVersion diz ao PHPCompatibility para verificar contra o PHP 8.3 e superiores. Isso é útil durante um upgrade de PHP e é tratado com mais profundidade em compatibilidade no upgrade para PHP 8.

Não aponte o ruleset para vendor ou generated. Código do core e de terceiros não é seu para corrigir pelo PHPCS, e a saída enterraria os seus próprios achados.

Níveis de severity

Cada achado no standard do Magento tem uma severity de 1 a 10. Os níveis mais altos são reservados para segurança e problemas críticos, os do meio para erros que devem ser corrigidos e os mais baixos para warnings e estilo. O PHPCS permite filtrar por severity:

vendor/bin/phpcs --severity=10
vendor/bin/phpcs --error-severity=1 --warning-severity=8

Uma abordagem prática é falhar o CI em erros, mostrar warnings em uma severity alta e ignorar os warnings de severity baixa até o time estar pronto para eles. Um padrão que produz centenas de warnings menores a cada execução treina as pessoas a parar de ler a saída.

Corrigindo automaticamente com phpcbf

O PHPCS vem com o phpcbf, que corrige os achados que têm correção automática:

vendor/bin/phpcbf app/code/Vendor/Shipping

Ele cuida de indentação, espaçamento, fins de linha, parte da formatação de docblocks e coisas parecidas. Não corrige achados que exigem julgamento, como escaping ou funções desencorajadas. Rode com a working tree limpa e revise o diff antes de commitar, porque uma mudança automática grande misturada com trabalho de verdade deixa o pull request difícil de revisar. Melhor ainda, faça o commit da correção de formatação separado.

Entendendo um achado

Um achado típico em um template:

<div class="label"><?= $block->getLabel() ?></div>

O sniff de XSS reporta isso como saída sem escaping. A correção depende do contexto:

<div class="label"><?= $escaper->escapeHtml($block->getLabel()) ?></div>
<a href="<?= $escaper->escapeUrl($block->getLink()) ?>" title="<?= $escaper->escapeHtmlAttr($block->getTitle()) ?>">

A variável $escaper está disponível em templates renderizados por blocks do Magento 2.4. Para saída que é HTML de propósito, como conteúdo de um campo WYSIWYG já processado por um filtro, o sniff aceita uma anotação @noEscape na tag de saída. Use só quando você conseguir explicar por que o valor é seguro.

Quando um achado está errado ou não se aplica, suprima na linha com o código específico do sniff em vez de desabilitar o sniff para o arquivo todo:

// phpcs:ignore Magento2.Functions.DiscouragedFunction
$content = file_get_contents($path);

Peça um motivo no code review toda vez que alguém adicionar um ignore. Muitas vezes a alternativa do framework é a correção de verdade, neste caso o driver de filesystem.

Verificando só os arquivos alterados

Em um codebase com anos de histórico, rodar o standard em tudo pela primeira vez retorna milhares de achados. Corrigir todos de uma vez é arriscado e ninguém quer revisar isso. A resposta prática é verificar só os arquivos alterados em um pull request:

git diff --name-only --diff-filter=ACMR origin/main...HEAD -- '*.php' '*.phtml' \
  | xargs -r vendor/bin/phpcs

Código novo precisa estar limpo. Arquivos antigos são limpos quando alguém mexe neles por outro motivo. Depois de alguns meses as partes mais ativas do codebase estão em conformidade, e as partes que nunca mudam podem ficar como estão.

Na IDE e no CI

O PhpStorm tem integração nativa com o PHP_CodeSniffer. Aponte para o vendor/bin/phpcs dentro do seu container ou use um interpretador remoto, habilite a inspeção e selecione o ruleset do projeto. Os achados aparecem enquanto você digita, o que é muito mais barato do que descobri-los no CI.

No CI, rode a verificação dos arquivos alterados nos pull requests e falhe o job em erros. O pipeline em o artigo sobre GitHub Actions tem um passo de PHPCS que você pode adaptar. Combine com análise estática, já que o PHPCS verifica como o código é escrito e o PHPStan verifica se ele está correto. O setup está em o artigo sobre PHPStan.

JavaScript e LESS

O pacote inclui regras de ESLint para o JavaScript do Magento. Se o seu projeto tem muito JS customizado, rode-as no ESLint com a configuração do pacote. Para LESS, o core do Magento usa convenções próprias documentadas no guia do desenvolvedor de frontend. Não há um linter oficial único rodado em projetos do core, então combinem um no time se precisarem. Em temas Hyva, o código de Tailwind e Alpine segue o tooling do próprio tema.

O que o standard não pega

Um relatório limpo do PHPCS não significa código bom. Ele não vai notar uma collection carregada em um loop, um plugin no método errado ou cacheable="false" em um handle de layout comum. Esses são assuntos de review. Use o standard para tirar ruído do code review e dar aos revisores tempo para os problemas que importam.

FAQ

O coding standard do Magento já está instalado no meu projeto?

Geralmente sim. Projetos criados a partir dos templates de projeto do Magento incluem o magento/magento-coding-standard como dependência de dev. Rode vendor/bin/phpcs -i para ver se Magento2 está na lista de standards instalados.

Qual severity o Magento Marketplace usa?

O technical review do Marketplace roda o mesmo standard e foca nos achados de severity mais alta. Confira a documentação atual do Marketplace para saber o limite exato antes de submeter uma extensão.

O phpcbf corrige tudo automaticamente?

Não. Ele corrige formatação, como espaçamento, indentação e alguns problemas de docblock. Achados sobre escaping, funções desencorajadas ou arquitetura exigem que um desenvolvedor mude o código.

Como começo a usar o PHPCS em um codebase legado grande?

Verifique só os arquivos alterados no CI. O código novo precisa estar limpo e o código antigo melhora conforme é tocado, sem um pull request gigante de limpeza única.

Atendo como freelancer em Magento e Adobe Commerce, incluindo limpeza de módulos legados e setup de verificações de qualidade. Se precisar de ajuda com isso, fale comigo.

Artigos relacionados