PHP pode ser a linguagem que mais sofre bullying nas redes por ter diversas aplicações meio “bagunçadas”. Porém, pessoalmente, acho a linguagem mais fácil de depurar por ser interpretada, não compilada e ter o var_dump() disponível.
Apenas com esta função, consegui resolver vários situações. Isso me ajudou bastante a entender diversos códigos, já que me incentivava a entrar em funções e entendê-las para saber qual variável analisar.
O que é debug?
Depurar, ou “debugar”, mais utilizado pelos desenvolvedores, é o procedimento de monitorar partes específicas do código para encontrar a raiz de certo erro.
Existem diversas ferramentas para auxiliar a fazer o debug de aplicações como o Whoops (uma biblioteca PHP para ajudar a ler exceções não previstas), mas aqui aprenderemos um jeito simples e prático de fazer debug em qualquer aplicação.
Lembrando que é muito importante que ative o display_errors no seu php.ini e deixe como padrão “mostrar todos os erros”. Caso não tenha essas configurações, a tela aparecerá em branco em exceções geradas pela aplicação e não será possível ver o erro na tela.
Na KingHost, para ativar essas configurações para sua aplicação, basta acessar o Painel de Controle -> Selecionar o seu Domínio -> Configuração PHP, ativar display_errors.
Quanto ao reporte de erros, coloque no arquivo global de sua aplicação o seguinte código:
error_reporting(E_ALL);
Bom como exemplo, vamos utilizar o pequeno trecho de código abaixo.
Exemplo de debug:
<?php class Cachorro { private $raca; private $nome; public function __construct() { $this->raca = 'Poodle'; $this->nome = 'Bob'; } public function setRaca($raca) { $this->raca = $raca; } public function setNome($nome) { $this->nome == $nome; } public function getInformacoes() { return "Meu cachorro é da raça {$this->raca} e o nome dele é {$this->nome}"; } } $cachorro = new Cachorro(); $cachorro->setRaca('Dogue Alemão'); $cachorro->setNome('Scooby'); echo $cachorro->getInformacoes();
Uma classe simples chamada Cachorro, que tem as funções de setar o nome (setNome) e a raça (setRaca). Há também uma função para disponibilizar as informações do cachorro na tela (getInformacoes) e caso não sejam setadas a raça ou o nome do cachorro, ele tem um construtor para definir os valores padrão “Poodle” para raça e “Bob” para o nome.
Mas se acessarmos o nosso código no navegador ou por um terminal veremos que o retorno é:
“Meu cachorro é da raça Dogue Alemão e o nome dele é Bob”;
Eu coloquei o nome Scooby com a função setNome, certo? Vamos aplicar o debug nesta aplicação.
Sempre temos que pensar em fazer a engenharia reversa, ou seja, quem está aparecendo errado? O nome!
Então vamos primeiro ver qual é a função que me retorna as informações do cachorro:
public function getInformacoes() { return "Meu cachorro é da raça {$this->raca} e o nome dele é {$this->nome}"; }
Temos que entender primeiramente o que esta função faz. É uma função básica que retorna uma string e, dentro dela, imprime os valores da raça e do nome deste objeto que está instanciado.
Debug utilizando var_dump() na prática
Se o nome está sendo impresso de forma errada, vamos matar a aplicação, antes de retornar a string completo e pedir para mostrar somente o valor do nome:
public function getInformacoes() { var_dump($this->nome);exit; return "Meu cachorro é da raça {$this->raca} e o nome dele é {$this->nome}"; }
A função var_dump, se traduzirmos livremente, “despejar variável”, faz exatamente isso: nos mostra todas as informações salvas dentro desta variável. Já a função exit, mata o script e não deixa mais nada ser executado;
Então se acessarmos a aplicação novamente, teremos o resultado impresso:
string(3) "Bob"
Bom, se o nome está sendo impresso corretamente e não está sendo alterado antes de retornar a nossa string, então temos que analisar onde está sendo setado este nome. Apague o var_dump e exit da função getInformacoes() e vamos analisar a função setNome():
public function setNome($nome) { $this->nome == $nome; }
Primeiramente vamos verificar se estamos recebendo o parâmetro correto:
public function setNome($nome) { var_dump($nome);exit; $this->nome == $nome; }
O resultado da aplicação:
string(6) "Scooby"
Estamos recebendo corretamente o valor do parâmetro, então, conseguimos ver assim que o erro está no momento em que atribuímos este valor à propriedade nome do objeto:
public function setNome($nome) { $this->nome == $nome; }
Então encontramos o erro, nesta função, estamos utilizando o símbolo de comparação (==), comparando a propriedade nome do objeto instanciado, cujo valor padrão é ‘Bob’, com o que estamos recebendo por parâmetro.
Basta arrumarmos isto na função:
public function setNome($nome) { $this->nome = $nome; }
E ao acessarmos teremos o resultado esperado:
"Meu cachorro é da raça Dogue Alemão e o nome dele é Scooby"
Este caso é simples, mas a técnica de var_dump + exit pode ser utilizada para investigar qualquer tipo de aplicação.
Vamos para outro caso:
class Cachorro { private $raca; private $nome; public function __construct() { $this->raca = 'Poodle'; $this->nome = 'Bob'; } public function setRaca($raca) { $this->raca = $raca; } public function setNome($nome) { $this->nome = $nome; } public function getInformacoes() { return "Meu cachorro é da raça {$this->raca} e o nome dele é {$this->nome}"; } } $cachorro = new Cachorro(); $cachorro->setRaca('Dogue Alemão'); $cachorro->setName('Scooby'); echo $cachorro->getInformacoes();
Ao acessarmos este script:
Uncaught Error: Call to undefined method Cachorro::setName()
Podemos ir utilizando a função ‘echo’ para imprimir uma mensagem de qual passo da aplicação estamos e ir matando ela até encontrar onde está o erro. Por exemplo:
$cachorro = new Cachorro(); echo 'Instanciei um objeto cachorro';exit; $cachorro->setRaca('Dogue Alemão'); $cachorro->setName('Scooby'); echo $cachorro->getInformacoes();
Ao acessarmos a aplicação, veremos que a mensagem “Instanciei um objeto cachorro” é mostrada, indicando que não é um erro na hora de instanciar o objeto.
Continuando:
$cachorro = new Cachorro(); $cachorro->setRaca('Dogue Alemão'); die('Informei a raca do meu cachorro'); $cachorro->setName('Scooby'); echo $cachorro->getInformacoes();
A função die, matar em inglês, é a junção da função echo com exit. Basta passar como parâmetro a mensagem que queremos disponibilizar, a mensagem é mostrada e o script morto.
E ao acessarmos a aplicação, veremos a mensagem “Informei a raça do meu cachorro”.
Mais uma vez:
$cachorro = new Cachorro(); $cachorro->setRaca('Dogue Alemão'); $cachorro->setName('Scooby'); die('setei o nome do cachorro'); echo $cachorro->getInformacoes();
Neste momento se acessar a aplicação veremos novamente:
Call to undefined method Cachorro::setName()
Então conseguimos identificar que o erro está no nome da função. Como diz o erro, “Call to undefined method Cachorro::setName()”, Chamada para um método não definido Cachorro::setName(), pois o nome da função na verdade é setNome().
Alterando o nome da função, a aplicação volta a funcionar normalmente.
O mesmo procedimento pode ser utilizado para depurar aplicações que utilizam algum framework MVC, algum CMS como WordPress ou Magento. Apenas com essas 4 funções ‘echo’, ‘var_dump’, ‘exit’, ‘die’, conseguimos entender o erro em qualquer aplicação PHP.
Debug com Xdebug
Também, caso queira ver melhor formatado os dados do var_dump, pode ser habilitada a extensão “xdebug” do php.
Por exemplo, caso eu queria ver os dados da variável $cachorro como ele é instanciado e depois quero utilizar o var_dump para ver os dados do cachorro após setar um nome, eu faço dessa maneira no código:
PHP $cachorro = new Cachorro(); var_dump($cachorro); $cachorro->setNome('Scooby'); var_dump($cachorro);exit;
O retorno deste código, sem ter o xdebug habilitado, será este:
PHP object(Cachorro)#1 (2) { ["raca":"Cachorro":private]=> string(6) "Poodle" ["nome":"Cachorro":private]=> string(3) "Bob" } object(Cachorro)#1 (2) { ["raca":"Cachorro":private]=> string(6) "Poodle" ["nome":"Cachorro":private]=> string(6) "Scooby" }
Ou seja, sem quebras de linha entre os objetos ou entre as propriedades do objeto, deixando mais difícil de ler este retorno.
Agora, vamos habilitar o xdebug.
Para isso, deves baixar a extensão para o PHP instalado em sua máquina.
Em Linux, basta instalar pelo terminal da sua máquina:
ShellScript sudo apt-get install php-xdebug
Em Windows, deves baixar a dll, colocar na pasta de extensões e adicioná-lo pelo php.ini:
Conteúdo php.ini zend_extension="c:\caminho\para\sua\pasta\de\extensoes\xdebug.dll" xdebug.remote_enable=1 xdebug.remote_port=9000
Em MacOSx:
pecl pecl install xdebug
ou acesse o site oficial do xdebug para encontrar as instruções de instalação de acordo com seu Sistema Opercional.
Agora com xdebug instalado, acesse novamente sua página que verás a saída do var_dump formatada:
PHP (xdebug_var_dump.png) /caminho/para/seu/script/index.php:37: object(Cachorro)[1] private 'raca' => string 'Poodle' (length=6) private 'nome' => string 'Bob' (length=3) /caminho/para/seu/script/index.php:39: object(Cachorro)[1] private 'raca' => string 'Poodle' (length=6) private 'nome' => string 'Scooby' (length=6)
Com quebras de linha e cores para melhor visualização.
Por último, também podemos utilizar a própria IDE para nos ajudar a debugar a aplicação, assim como as IDE’s de linguagens compiladas.
Como exemplo, utilizaremos aqui o PHPStorm.
Primeiramente, devemos garantir que o PHPStorm está conseguindo se comunicar com o xdebug.
Vá em File > Settings > Languages & Frameworks > PHP > Debug
Normalmente a IDE já vem configurada corretamente, mas para testar, clique em “Validate debugger configuration on the Web Server” para ser executado um script para checar a instalação do seu XDebug.
“Em Path to create validation script” coloque o caminho para ser gerado o script e “Url to validation script” a url para acessar o mesmo:
Após garantir que a IDE consegue conversar com o xdebug, baixe a extensão para o seu navegador conversar com a IDE. Neste link, há a lista das extensões de acordo com seu navegador favorito:
Agora podemos fazer a validação.
No PHPStorm, marque até qual linha desejas fazer a depuração clicando no número da linha:
No seu navegador, ative a extensão e acesse o seu script de teste, o que fará com que você seja imediatamente redirecionado para o seu PHPStorm e veja o passo a passo do que está sendo feito:
Esse comentários em cinza são gerados pela própria IDE se comunicando com o Xdebug, e com isso, conseguimos entender que na função setNome está sendo recebido o valor “Scooby“, mas, a propriedade nome continua como “Bob“.
Então, vimos que com PHP temos diversas abordagens para depurar uma aplicação, combinar o var_dump com xdebug, com uma IDE, ou apenas utilizar o var_dump no script.
De todas as maneiras, fazer a depuração em PHP é simples e ágil.
E aí, curtiu o material? Caso tenha surgido alguma dúvida, escreva pra gente ali nos comentários.
Quer saber mais sobre linguagens de programação? Confira os conteúdos do nosso Blog da KingHost.
O que você achou deste conteúdo?