phpcs com o Magento Coding Standard: o que ele pega e o que deixa passar
O Magento Coding Standard é o conjunto de regras do PHP_CodeSniffer que a Adobe recomenda para extensões. O composer.json do Magento 2.4.9 já traz o pacote no require-dev, junto com o plugin do Composer que registra o padrão no phpcs. O primeiro comando abaixo mostra se o padrão Magento2 está instalado; se não estiver, o segundo instala, e o README oficial traz o passo para registrá-lo quando ele não aparece na lista. Se o vendor/ da produção foi instalado com composer install --no-dev, o phpcs nem existe ali; rode no staging ou na máquina do dev:
vendor/bin/phpcs -i
composer require --dev magento/magento-coding-standard
vendor/bin/phpcs --standard=Magento2 app/code/Vendor/ModuloPara saber até onde confiar nele, montei um módulo de teste com dez problemas de propósito e rodei a versão 41 do padrão, a mais recente no Packagist em 16/09/2026. O resultado:
| Problema plantado | O que o phpcs apontou sobre o problema |
|---|---|
Dado exibido sem escape num .phtml | ERROR (Security.XssTemplate) |
$_POST lido direto no controller | ERROR (Security.Superglobal) |
SQL com variável concatenada num fetchAll() | Nada |
ObjectManager::getInstance() dentro de classe | Nada |
load() de produto dentro de um loop | Nada |
Plugin around que só chama o método original | Nada |
Controller de admin sem ADMIN_RESOURCE | Nada |
Rota DELETE com resource ref="anonymous" no webapi.xml | Nada |
cacheable="false" no layout da página de produto | Nada |
Arquivo PHP sem declare(strict_types=1) | Nada |
Além dos dois erros, a saída trouxe avisos de docblock ausente e de método de escape obsoleto, nenhum sobre os outros oito problemas.
O caso do SQL tem explicação no próprio código do padrão: a regra de SQL bruto só avisa quando a string com o comando SQL é atribuída a uma variável ou passada para query(). Na prática: phpcs com zero ERROR é condição para aceitar, nunca prova de que o módulo está bom.
Como revisar o código de um módulo Magento: o checklist em blocos
Estrutura
registration.phpeetc/module.xmlcom o mesmo nome, esequencelistando os módulos de que ele depende.composer.jsoncom"type": "magento2-module"e as versões de PHP e demagento/frameworkdeclaradas.- Vendor igual ao combinado; se a loja não combinou, veja por que o nome do vendor importa.
Compilação e banco, no staging
bin/magento module:enable Vendor_Modulo
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:db-declaration:generate-whitelist --module-name=Vendor_Modulo- O
setup:di:compileprecisa terminar comGenerated code and dependency injection configuration successfully.Se quebra ali, quebra o deploy em modo de produção. - Tabelas em
etc/db_schema.xml, comdb_schema_whitelist.jsongerado pelo último comando: segundo a documentação, coluna só pode ser removida depois se constar na whitelist. - Rodar
setup:upgradeduas vezes não duplica dados; patch que depende de outro declaragetDependencies().
Segurança, uma linha por item
- Saída dos templates passando por
$escaper. - Todo controller de admin com
ADMIN_RESOURCEpróprio; sem ele, vale o padrão herdadoMagento_Backend::admine o controle por papel se perde. anonymousnowebapi.xmlsó em rota que é pública de verdade, nunca em rota que altera dados.- SQL com parâmetros, como pede a diretriz técnica 15.1 da Adobe, e nada de
eval,unserializeoushell_exec(diretriz 15.10.1).
Desempenho
cacheable="false"em layout de página de catálogo: um bloco desses tira a página inteira do cache.- Plugin
aroundsó quando o comportamento original é substituído, como diz a diretriz 4.1; a escolha entre plugin, preference e observer pesa no próximo upgrade. - Nada de carregar produto ou pedido um a um dentro de loop quando uma coleção filtrada resolve.
Documentação
- README com instalação, caminhos de configuração, recursos de ACL, crons e como remover o módulo.
Os sinais que o phpcs não vê dão para puxar com grep, na raiz da loja. Cada linha devolvida é uma pergunta para o dev, não uma condenação automática:
grep -rn 'ref="anonymous"' app/code/Vendor/Modulo --include=webapi.xml
grep -rL "ADMIN_RESOURCE" app/code/Vendor/Modulo/Controller/Adminhtml --include=*.php
grep -rn 'cacheable="false"' app/code/Vendor/Modulo --include=*.xml
grep -rn "ObjectManager::getInstance" app/code/Vendor/Modulo --include=*.php
grep -rn "function around" app/code/Vendor/Modulo --include=*.php
grep -rL "strict_types" app/code/Vendor/Modulo --include=*.php
Quando pagar uma revisão de código independente e como contratar sem briga
Vale pagar outra pessoa para revisar quando o módulo mexe em checkout, pagamento, preço ou dados pessoais, quando o dev é novo e ainda não tem histórico com a loja, e antes da última parcela de um projeto grande. Ajuste de template pequeno não justifica.
Para não virar briga entre revisor e autor, eu combino quatro coisas por escrito:
- Aviso prévio. O dev sabe, desde a especificação, que a entrega passa por revisão externa.
- Escopo fechado. Quais módulos e qual tag ou commit serão revisados.
- Formato do relatório. Cada item com arquivo e linha, severidade, evidência e sugestão. Opinião de estilo fica separada de defeito.
- Direito de resposta. O autor responde cada item antes do aceite, e o revisor aponta sem corrigir.
Para contratar uma revisão nesse formato, fale comigo.
Perguntas frequentes
Quem não programa consegue usar esse checklist de code review?
Consegue usar a parte objetiva: pedir a saída do phpcs e do setup:di:compile e rodar ou pedir os greps de rota anônima, cacheable false e controller sem ADMIN_RESOURCE. A leitura do código em si, como SQL e plugins, pede alguém que programe em Magento.
phpcs sem erro quer dizer que o código é bom?
Não. Num módulo de teste com dez problemas plantados, o phpcs com o Magento Coding Standard apontou só a saída sem escape no template e o uso direto de $_POST. SQL concatenado, ObjectManager, rota anônima e controller sem ACL passaram sem aviso.
Quanto tempo leva um code review de módulo Magento?
Depende do tamanho do módulo e de quanto ele encosta em checkout, preço e integrações. Peça ao revisor a estimativa depois de ele ver a lista de arquivos e o diff. Rodar os comandos é rápido; o que consome tempo é ler as regras de negócio contra a especificação.
Fontes oficiais
- Magento Coding Standard (README: instalação e uso) (Magento (Adobe) no GitHub)
- composer.json do Magento 2.4.9 (require-dev com o Magento Coding Standard) (Magento no GitHub)
- Technical guidelines (Adobe Commerce Developer)
- Code compiler (setup:di:compile) (Adobe Experience League)
- Configure declarative schema (whitelist) (Adobe Commerce Developer)
- Define web API services (resource anonymous) (Adobe Commerce Developer)
- Create access control list rule (ADMIN_RESOURCE) (Adobe Commerce Developer)
- Cross-site scripting (XSS) prevention (Adobe Commerce Developer)
- Configure a cacheable page (public content) (Adobe Commerce Developer)