MP-08 - Depurem programes php
Al programar la part del backend en llenguatge php ens trobarem amb molt problemes a l'hora de depurar els programes i els errors que no veurem enlloc. Per tant, una sèrie de recomanacions que cal seguir sí o sí.
Suposarem que tenim el servidor web iniciat. Caldrà obrir una shell i mirar la informació que es va acumulant al fitxer de log dels errors.
Ara només cal executar la comanda necessària per veure el contingut del fitxer /var/log/apache2/error.log
tail /var/log/apache2/error.log
En aquest cas la comanda s'executarà i tornarem a la shell.
Fitxers de log: access.log
i error.log
Apache, com la majoria de serveis en Linux va guardant un diari del que li va passant. En Linux el directori on es guarden tots els fitxers de log sol ser /var/log
.
Apache crea un subdirectori dins aquest directori de manera que els fitxers de l'apache els trobarem a /var/log/apache2
. En concret ens interessen dos fitxers:
-
access.log
: emmagatzema totes les peticions que rep el servidor i a més indica si s'ha pogut servir o bé altres possibilitats com ara 404 NOT FOUND -
error.log
: emmagatzema tots els errors produits ja sigui per errors al fitxer.htaccess
com per errors dels nostres scriptsphp
o altres.
En el nostre cas, serà bo SEMPRE mirar el fitxer /var/log/apache2/error.log
per a poder depurar més fàcilment els nostres programes. Per això utilitzarem la comanda linux tail
que ens permet veure les darreres línies d'un fitxer.
Executada per defecte tail /var/log/apache2/error.log
ens mostra les 10 darreres línies.
Una bona opció és utilitzar el paràmetre -f
que ens deixa oberta la comanda i va mostrant les línies a mesura que n'hi van arribant més. També podem especificar-li quantes en volem veure inicialment. Si posem que no en volem veure cap -n 0
i que es quedi mostrant-nos les que li arribin, serà una bona forma de poder tenir una terminal que ens vagi mostrant sempre els errors que vagin arribant al servidor. Com que el servidor està en un contenidor, proposo utilitzar la comanda següent des de la màquina real:
tail -n 0 -f /var/log/apache2/error.log
Exemple error.log
tail -n 0 -f /var/log/apache2/error.log
[Mon Mmm DD HH:MM:SS AAAA] [php7:error] [pid 479] [client 172.17.0.1:53392] PHP Fatal error: Class LlibreController contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Controller::process) in /var/www/html/Montilivi/bundle/Llibre/controllers/LlibreController.php on line 0
[Mon Mmm DD HH:MM:SS AAAA] [php7:error] [pid 501] [client 172.17.0.1:53372] PHP Parse error: syntax error, unexpected 'else' (T_ELSE), expecting function (T_FUNCTION) or const (T_CONST) in /var/www/html/Montilivi/bundle/Llibre/controllers/LlibreController.php on line 38
[Mon Mmm DD HH:MM:SS AAAA] [php7:notice] [pid 527] [client 172.17.0.1:53412] PHP Notice: Undefined variable: paramametre1 in /var/www/html/Montilivi/bundle/Llibre/controllers/LlibreController.php on line 33
-
Al primer error ens parla d'una Classe que hem definit i que li falta un mètode abstracte per a especificar.
-
Al segon error veiem que ens indica que a la línia 38 del fitxer
/var/www/html/Montilivi/bundle/Llibre/controllers/LlibreController.php
hi ha una sentènciaelse
inesperada. Esperava una funció o una constant. -
El tercer és un Warning i ens indica que tenim una variable
paramametre1
sense definir. Segurament volia serparametre1
.
Vigileu-ho tot!
Cal vigilar els errors i també els warnings. No n'hi hauria d'haver cap a les nostres aplicacions.
Exemple access.log
172.17.0.1 - - [Mon Mmm DD HH:MM:SS AAAA] "GET /Montilivi/ HTTP/1.1" 200 939 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
172.17.0.1 - - [Mon Mmm DD HH:MM:SS AAAA] "GET /Montilivi/styles/style.css HTTP/1.1" 200 949 "http://localhost/Montilivi/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
172.17.0.1 - - [Mon Mmm DD HH:MM:SS AAAA] "GET /favicon.ico HTTP/1.1" 404 487 "http://localhost/Montilivi/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
172.17.0.1 - - [Mon Mmm DD HH:MM:SS AAAA] "GET /Montilivi/aaa.html HTTP/1.1" 200 858 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
172.17.0.1 - - [Mon Mmm DD HH:MM:SS AAAA] "GET /Montilivi/aaa.css HTTP/1.1" 404 488 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"
Fitxer php.ini
El llenguatge php el tenim instal·lat al fitxer del servidor /etc/php/8.1
. Entre d'altres, hi ha un fitxer molt important anomenat apache2/php.ini
. Aquest fitxer, i els que trobem a apache2/conf.d
, que podem modificar en qualsevol moment, gestionen alguns paràmetres importants que veurem.
Per a saber a quin fitxer tenim algun dels paràmetres recomano la següent instrucció:
grep -irn <paraula_a_buscar> /etc/php/8.1/apache2
Per exemple
grep -irn display_errors /etc/php/8.1/apache2
/etc/php/8.1/apache2/php.ini:97:; display_errors
/etc/php/8.1/apache2/php.ini:503:display_errors = Off
/etc/php/8.1/apache2/php.ini:506:; separately from display_errors. We strongly recommend you set this to 'off'
Podem veure que el paràmetre display_errors apareix al fitxer php.ini en 3 línies diferents: 97, 503 i 506. En dues d'elles sí és un paràmetre comentat ja que la línia comança per punt i coma ;
. L'important és que la línia no comentada diu Off el que indica que no veiem els errors.
Tipus d'errors mostrats
A la línia 486 hi tenim el paràmetre error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
que ens indica els tipus d'errors que es reporten. Si en volem més tipus, caldrà indicar-ho afegint els tipus d'error, explicats a les línies superiors, de forma correcta.
Podem posar el paràmetre a On però continuament veurem els errors en pantalla (navegador) i ens pot molestar molt. Vegem-ho en un exemple:
Exemple 1 |
---|
![]() |
En aquest cas veiem que l'error apareix en una pàgina buida degut al tipus d'error però en altres casos ens pot aparèixer enmig de la nostra pàgina web i d'altres vegades, pot no veure's ja que de vegades saltarem directament a altres pàgines amb el mètode redirect.
Exemple 2 | Exemple 3 |
---|---|
![]() |
![]() |
Per tant no crec que la millor forma de veure els errors sigui tenir-los enmig de la nostra pàgina web, tot i que si treballem amb el servidor fora de la nostra màquina potser serà el més recomanable.
Xivatos en php
Una bona manera de saber què tenim en cadascuna de les variables en un moment determinat és mostrar-les per algun lloc. En php tenim la opció d'enviar missatges "per pantalla" i es veuran enmig de la nostra pàgina web o bé enviar-los al fitxer d'errors.
Per això tenim les comandes de php:
error_log
La comanda error_log
permet enviar missatges al fitxer error.log.
Si afegim la comanda error_log("Missatge numero 1");
dins un codi php que s'executi, podrem veure al fitxer d'errors el missatge.
tail -n 0 -f /var/log/apache2/error.log
[Mon Mmm DD 16:34:57.562407 2022] [php7:notice] [pid 33] [client 172.17.0.1:53428] Missatge numero 1`
El problema el tenim quan el que volem mostrar és un array o un objecte o bé no sabem ben bé què és. Per això recomanem mostrar les dades dins la pàgina web però millor si les formatem amb l'etiqueta <pre>
. Recorda que tenim dues comandes importants:
-
print_r
: mostra el contingut d'un array -
var_dump
: mostra el tipus de la variable i el seu contingut.
Per tant, serà una bona proposta escriure alguns xivatos d'una manera semblant a:
echo "<pre>";
print_r($variable_que_es_un_array);
var_dump($variable_Objecte_o_Que_no_sabem_el_tipus);
var_dump($v1, $v2, $v3);
echo "</pre>";
i un mixte
Com que la funció print_r
admet un segon paràmetre que en cas de ser true
no imprimeix el contingut sinó que en retorna un string
amb la seva representació sempre podem escriure:
error_log(print_r($variable_que_conte_l_array, true));
Classe estàtica?
I si et veus capaç de fer una Classe amb un mètode estàtic que mostri el que vulguis, millor que millor. Això ja està a les teves mans.