Atualizando um aplicativo PHP antigo



Recentemente, tive a oportunidade ocasional de trabalhar com vários aplicativos PHP antigos. Notei alguns antipadrões comuns que precisaram ser corrigidos. Este artigo não é sobre como reescrever um aplicativo PHP antigo para <inserir o nome da estrutura maravilhosa aqui>, mas como torná-lo mais sustentável e menos incômodo de trabalhar.



Antipadrão # 1: credenciais no código



Este é o mais comum dos piores padrões que encontrei. Em muitos projetos, o código com versão é codificado permanentemente com informações importantes, como nomes e senhas para acessar o banco de dados. Obviamente, esta é uma má prática, pois não permite a criação de ambientes locais, pois o código está atrelado a um ambiente específico. Além disso, qualquer pessoa com acesso ao código pode ver as credenciais geralmente apropriadas para o ambiente de produção.



Para corrigir isso, prefiro um método que funcione para qualquer aplicativo: instale o pacote phpdotenv , que permite criar um arquivo de ambiente e acessar variáveis ​​usando supervariáveis ​​de ambiente.



Vamos criar dois arquivos: .env.exampleum que terá uma versão e servirá como modelo para o arquivo.env, que conterá as credenciais. O arquivo .envnão tem versão, então adicione-o a .gitignore. Isso está bem explicado na documentação oficial .



Seu arquivo .env.examplelistará as credenciais:



DB_HOST=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=


E os próprios dados estarão no arquivo .env:



DB_HOST=localhost
DB_DATABASE=mydb
DB_USERNAME=root
DB_PASSWORD=root


Em um arquivo normal, carregue .env:



$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();


Pode então aplicar-se aos dados contábeis usando, digamos $_ENV['DB_HOST'].



Não é recomendável usar o pacote em operação "tal como está", para isso é melhor:



  • Injete variáveis ​​de ambiente no tempo de execução do seu contêiner, se você tiver uma implantação baseada em Docker, ou na configuração HTTP do lado do servidor, se possível.
  • Variáveis ​​de ambiente de cache para evitar a sobrecarga de leitura de .env em cada solicitação. É assim que o Laravel faz .


Os arquivos de credencial podem ser removidos do histórico do Git .



Antipadrão 2: não use o Composer



Costumava ser muito popular ter uma pasta lib com grandes bibliotecas como o PHPMailer. Isso deve ser evitado de todas as maneiras possíveis quando se trata de controle de versão, portanto, essas dependências devem ser gerenciadas com o Composer . Assim, será muito fácil para você ver qual versão do pacote está em uso e atualizá-la se necessário.



Portanto, instale o Composer e use-o para gerenciar.



Antipadrão # 3: nenhum ambiente local



A maioria dos aplicativos com os quais trabalhei tinha apenas um ambiente: produção.





Mas, ao se livrar do anti-padrão nº 1, você pode personalizar facilmente seu ambiente local. Talvez parte de sua configuração tenha sido codificada em seu código, como os caminhos de inicialização, mas agora você pode mover para .env.



Eu uso o Docker para criar ambientes locais. Funciona especialmente bem para projetos mais antigos porque eles geralmente usam versões mais antigas do PHP que você não quer ou não pode instalar.



Você pode usar um serviço como o PHPDocker ou usar um pequeno arquivo docker-compose.yml.



Antipadrão # 4: não use a pasta Pública



Acontece que a maioria desses projetos antigos pode ser acessada em suas pastas raiz. Ou seja, qualquer arquivo na raiz estará disponível para leitura pública. Isso é especialmente ruim quando os invasores (como um script infantil) tentam acessar os arquivos incluídos diretamente, porque você pode não ser capaz de determinar a saída se o script acessar todos os arquivos incluídos diretamente.



Obviamente, essa situação é incompatível com o uso do .envou Composer, porque abrir a pasta do fornecedor é uma má ideia . Sim, existem alguns truques para fazer isso; mas, se possível, mova todos os arquivos PHP abertos para os clientes para uma pasta Publice altere a configuração do servidor para que essa pasta se torne a pasta raiz do seu aplicativo.



Eu normalmente faço isso:



  • Crie uma pasta dockerpara arquivos relacionados ao Docker (Nginx config, PHP Dockerfile, etc.).
  • Crio uma pasta appna qual armazeno a lógica de negócios (serviços, classes, etc.).
  • Crio uma pasta publicna qual armazeno scripts e recursos PHP (JS / CSS) abertos aos clientes. Esta é a pasta raiz do aplicativo do ponto de vista dos clientes.
  • Eu crio arquivos .enve .env.example.


Antipadrão 5: problemas de segurança flagrantes



Aplicativos PHP, especialmente os mais antigos que não usam estruturas, muitas vezes sofrem de graves problemas de segurança:



  • Devido à falta de escape de parâmetros na consulta, existe o perigo de injeção de SQL. Para evitá-los, use o PDO!
  • Existe o perigo de injeção de XSS devido à exibição de dados do usuário sem escape. Use htmlspecialchars para evitá-los.
  • . , , , .
  • - CSRF-. Anti-CSRF, .
  • Criptografia de senha ruim. Já vi muitos projetos ainda usarem SHA-1 e até MD5 para hashing de senha. O PHP 5.5 pronto para uso tem um bom suporte para BCrypt, é uma pena não usá-lo. Para transferir senhas de maneira confortável, prefiro atualizar os hashes no banco de dados à medida que os usuários fazem login. O principal é ter certeza de que a coluna passwordé longa o suficiente para acomodar as senhas do BCrypt, VARCHAR (255) está bem. Aqui está o pseudocódigo para torná-lo mais claro:



    <?php
    //    :    $
    //  :     
    if (strpos($oldPasswordHash, '$') !== 0 &&
        hash_equals($oldPasswordHash, sha1($clearPasswordInput))) {
        $newPasswordHash = password_hash($clearPasswordInput, PASSWORD_DEFAULT);
    
        //   password
    
        //  :    
    }
    
    //   
    if (password_verify($clearPasswordInput, $currentPasswordHash)) {
        //  :    
    }
    
    //   :    
    


Antipadrão # 6: sem testes



Isso é muito comum em aplicativos mais antigos. É quase impossível começar a escrever testes de unidade para todo o aplicativo, então você pode escrever testes funcionais.





Esses são testes de alto nível para ajudá-lo a garantir que a refatoração subsequente de seu aplicativo não o interrompa. Os testes podem ser simples, por exemplo, iniciamos o navegador e entramos no aplicativo, a seguir aguardamos o código HTTP sobre o sucesso da operação e / ou a mensagem correspondente na página final. Para testes, você pode usar PHPUnit ou Cypress ou codeception .



Antipadrão nº 7: Tratamento de erros insatisfatório



Se (ou provavelmente quando) algo quebrar, você precisa descobrir rapidamente. Mas muitos aplicativos antigos não lidam bem com os erros, dependendo da leniência do PHP.



Você precisa ser capaz de detectar e registrar o máximo de erros possível para corrigi-los. Existem bons artigos sobre este assunto .



Além disso, será mais fácil encontrar locais onde ocorrem erros se o sistema lançar exceções específicas.



Antipadrão # 8: variáveis ​​globais



Achei que nunca mais os veria até começar a trabalhar com projetos antigos. Variáveis ​​globais tornam a leitura e compreensão do comportamento do código imprevisível. Resumindo, é mau .



É melhor usar injeção de dependência , porque permite controlar quais instâncias são usadas e onde. Por exemplo, o pacote Pimple teve um bom desempenho .



O que mais pode ser melhorado?



Dependendo do destino do aplicativo ou do orçamento, existem várias outras etapas que você pode seguir para melhorar seu projeto.



Primeiro, se o aplicativo estiver rodando em uma versão anterior do PHP (abaixo de 7), tente atualizá-lo. Na maioria das vezes, isso não causa grandes problemas e, acima de tudo, levará a maior parte do tempo para se livrar das ligações mysql_ calls, se houver. Para corrigir isso rapidamente, você pode usar uma biblioteca semelhante , mas é melhor reescrever todas as solicitações de PDO para que todos os parâmetros tenham escape ao mesmo tempo.



Se o aplicativo não usa o padrão MVC, ou seja, a lógica de negócios e os modelos são separados, então é hora de adicionar uma biblioteca de modelos (eu sei que PHP é uma linguagem de modelos, mas as bibliotecas modernas são muito mais convenientes), por exemplo, Smarty, Twig ou Blade.



Finalmente, a longo prazo, é melhor reescrever seu aplicativo em uma estrutura PHP moderna como Laravel ou Symfony. Você terá todas as ferramentas de que precisa para um desenvolvimento de PHP seguro e inteligente. Se o aplicativo for grande, eu recomendo usar o padrão strangler para evitar a reescrita big bang , que pode (e provavelmente terminará) mal. Portanto, você pode migrar aquelas partes do código nas quais está trabalhando atualmente para o novo sistema, mantendo as partes de trabalho antigas intactas até que cheguem até elas.



Esta é uma abordagem eficaz que permite criar um ambiente PHP moderno para o seu dia a dia de trabalho, sem congelar recursos por semanas ou meses, dependendo do projeto.



All Articles