Kako omogućiti ili onemogućiti prikaz pogreške u PHP-u? Prethodne poruke o grešci

02.04.2020 Vijesti


U prethodnom vodiču pokrili smo osnove rukovanja iznimkama i razlike između iznimaka i pogrešaka. U ovoj lekciji proučit ćemo postupke rješavanja pogrešaka.


Greške u PHP-u mogu se podijeliti na korisničke i sistemske. Nažalost, presretanje sistemske greške standardnim sredstvima je nemoguće i jedini način da se nosite s njima je ispravno napisati i otkloniti pogreške koda. Jedino što se može (i treba) učiniti je spriječiti da se poruke o pogrešci prikazuju u pregledniku. To se radi pomoću funkcije error_reporting(). Jedini parametar ove funkcije određuje koje se pogreške smiju ispisati pregledniku.

Parametar funkcije može biti kombinacija sljedećih konstanti

Stalni opis
E_GREŠKA Kritične pogreške, prekidanje izvršavanja skripte (na primjer, pogreška dodjele memorije)
E_UPOZORENJE Upozorenja
E_PARSE Pogreške u sintaksi izvornog koda
E_OBAVIJEST Bilješke
E_CORE_ERROR Kritične pogreške koje se javljaju tijekom faze pokretanja izvršavanja skripte
E_CORE_UPOZORENJE Upozorenja koja se pojavljuju tijekom pokretanja
E_COMPILE_ERROR Greške kompilacije
E_COMPILE_WARNING Upozorenja o kompilaciji
E_USER_ERROR Pogreške korisnika, stvoren pomoću funkcije trigger_error().
E_USER_WARNING Prilagođena upozorenja stvorena pomoću funkcije trigger_error().
E_USER_NOTICE Prilagođene bilješke stvorene pomoću funkcije trigger_error().
E_SVE svi moguće greške, upozorenja i napomene
E_STRIKTNO Bilješke o vremenu izvođenja
E_RECOVERABLE_ERROR Kritične pogreške koje dopuštaju daljnje izvršavanje koda.

Na primjer:

Ponekad se javljaju slučajevi kada je potrebno onemogućiti izlaz pogreške ne za cijelu skriptu, već samo za njen dio. U tom slučaju morate koristiti operator za suzbijanje pogrešaka "@" (pas). Kada se postavi ispred izraza, ovaj operator sprječava prikazivanje poruka, upozorenja ili obavijesti koje generira izraz. Na primjer:

Korisničke pogreške mogu se lako uhvatiti i obraditi, a rukovanje pogreškama osmišljeno je na takav način da se može izvršiti bez prekida glavne skripte.

Za generiranje pogreške upotrijebite funkciju trigger_error(), kojoj se prosljeđuju dva parametra - vrsta pogreške i njezin stvarni tekst. Vrsta pogreške određena je standardnim konstantama o kojima se govorilo gore.

Na primjer:

Pozivanje funkcije trigger_error ne dovodi do hitnog prekida skripte, što znači da će se sav sljedeći kod normalno izvršiti. Ako je i dalje potrebno prekinuti izvođenje, tada programer to mora učiniti "ručno" pomoću jezičnih alata.

Kao i kod iznimaka, možete instalirati vlastiti rukovatelj greškama. To se radi pomoću funkcije set_error_handler(), kojoj se prosljeđuje naziv funkcije rukovatelja i popis vrsta pogrešaka za koje se ova funkcija poziva. Funkcija ima četiri parametra: broj pogreške, tekst pogreške, naziv datoteke i broj retka u kojem se pogreška pojavila. Na primjer:

Ako funkcija obrade pogrešaka vrati true, tada se interni PHP rukovatelj ne poziva, a ako je false, tada će nakon izlaska iz korisničke procedure pogreška biti proslijeđena standardnom internom rukovatelju. To omogućava programeru da odgovori samo na dio grešaka koje se pojave, ostavljajući ostatak standardnim PHP rukovateljima.

Prethodni rukovatelj možete vratiti pozivom funkcije restore_error_handler():

Na taj način možete po potrebi uključiti i isključiti rukovatelje greškama. Ali ne biste trebali pretjerivati ​​s takvim operacijama - vjerojatnost da ćete se zbuniti i pomiješati rukovatelje je prevelika. U većini slučajeva dovoljan je jedan, ali dobro napisan rukovatelj, koji zapisuje pogreške u log datoteku ili bazu podataka, šalje ih na e-mail administratora i izvodi druge korisne operacije.

Rješavanje pogrešaka jedan je od najvažnijih elemenata skriptiranja. Loše napisana skripta može postati ne samo glavobolja za webmastera ili administratora stranice. "Loša" (od riječi "bug" - greška) skripta predstavlja ozbiljnu sigurnosnu prijetnju. U rukama vještog hakera, tekst pogreške pretvara se u glavni ključ koji omogućuje pristup cjelokupnom sadržaju stranice, a možda i poslužitelju.

Sastavni dio programiranja je prepoznavanje grešaka u kodu. Čak i ako je programer briljantan programer, i dalje će činiti pogreške, ponekad čak i trivijalne. Tome olakšava sama ljudska priroda. Stoga, programer provodi prilično velik dio svog vremena ispravljajući pogreške i identificirajući pogreške u kodu. U skladu s tim, što su alati za prepoznavanje pogrešaka u kodu fleksibilniji i praktičniji i što ih programer bolje poznaje, to je njegova produktivnost veća.

Budući da je PHP skriptni programski jezik, sve pogreške napravljene u kodu identificiraju se dok se kod izvršava. PHP programer morat će se nositi i sa standardnim pogreškama svojstvenim programiranju općenito, i prilično skrivenim pogreškama - kao što su tipfeleri u imenovanju varijabli.

Jezik PHP pruža dva mehanizma za otkrivanje grešaka u skripti tijekom njenog izvođenja: standardni mehanizam PHP greške i mehanizam iznimke. U PHP-u mnoge funkcije koriste standardni mehanizam pogreške, tako da je nemoguće ne znati za to. Stoga će se ovaj članak usredotočiti na ovaj mehanizam.

Standardni PHP mehanizam pogreške je prilično jednostavan - ako PHP interpreter naiđe na pogrešku tijekom izvršavanja skripte, pokušava o tome obavijestiti programera. Međutim, postoji dosta postavki za ovaj mehanizam, tako da ih je programeru koji poznaje PHP dosta teško razumjeti.

Vidimo greške

Dakle, kako bi PHP prikazivao pogreške izravno na stranici, trebate postaviti poseban parametar u kodu:

ini_set("pogreške_prikaza", 1); //display_errors odgovoran je za prikazivanje pogrešaka izravno na stranici. Ako je 0 – greške se ne prikazuju

Sada, ako se pojavi bilo kakva pogreška u skripti, tumač će prikazati informacije o tome na stranici. Na primjer, ako pokrenete skriptu s nepostojećom funkcijom:

ini_set("pogreške_prikaza", 1);
jeka "

Niz za prikaz

";
echo abrakadabra();
jeka "

Redak koji se neće prikazati zbog greške

";

tada će se na stranici prikazati sljedeća pogreška:

Fatalna greška. Ova vrsta pogreške znači da je skripta prekinuta i da se sljedeći kod neće izvršiti.

Prikazivanje pogrešaka skripte na stranici koristi se samo za otklanjanje pogrešaka u samoj skripti, tako da je kod pokretanja koda u produkciji parametar display_errors postavljen na 0.

Općenito, u PHP-u postoje pogreške različitih kategorija značaja: neke od njih prekidaju daljnje izvođenje koda - druge ne, neke se mogu presresti - druge ne. Potpuni popis kategorija pogrešaka dan je u nastavku:

Značenje
Konstantno
Opis
Prilika
1
E_GREŠKA
Fatalna greška
Ne
2
E_UPOZORENJE
Greška koja se može ispraviti
Da
4
E_PARSE
Greška parsera
Ne
8
E_OBAVIJEST
Potencijalna greška
Da
16
E_CORE_ERROR
Slično kao E_ERROR, ali generirano od strane PHP jezgre
Ne
32
E_CORE_UPOZORENJE
Slično kao E_WARNING, ali generirano PHP jezgromNe
64
E_COMPILE_ERROR
Slično E_ERROR, ali generirano Zend Engineom
Ne
128
E_COMPILE_WARNING
Slično E_WARNING, ali generirano Zend EngineomNe
256
E_USER_ERROR
Slično E_ERROR, ali se pokreće pozivom trigger_error()
Da
512
E_USER_WARNING
Slično E_WARNING, ali se pokreće pozivom trigger_error()Da
1024
E_USER_NOTICE
Slično E_NOTICE, ali se pokreće pozivom trigger_error()Da
2048
E_STRIKTNO
Poruka iz runtimea s preporukama za poboljšanje kvalitete koda (počevši od PHP5)
-
4096
E_RECOVERABLE_ERROR
Opasna, ali ne kobna pogreška (na primjer, neslaganje tipa)
Da
8192
E_ZASTARJELO
Upozorenje o zastarjeloj značajci ili funkciji
Da
16384
E_USER_DEPRECATED
U kodu se pojavljuje upozorenje o zastarjeloj funkciji ili značajci
Da
32767
E_SVE
Sve greške
Ne

Radi praktičnosti, dane su konstante koje se koriste za određivanje razine obrade pogreške i konstruiranje bit maske. Konstante imaju smislena imena. Gledajući konstantu - možemo reći da se pogreška razine E_PARSE javlja u slučaju sintaktičke pogreške, E_NOTICE je podsjetnik programeru o kršenju "dobrog stila" PHP programiranja.

Prema zadanim postavkama, način generiranja poruke o pogrešci je E_ALL & ~E_NOTICE, što odgovara izlazu svih poruka koje nisu klasificirane kao E_NOTICE. Programer može fleksibilno konfigurirati koje kategorije pogrešaka treba vidjeti na stranici. Kako biste promijenili način generiranja pogreške, trebate promijeniti konfiguracijski parametar error_reporting. Da biste omogućili prikaz bilo koje pogreške, morate postaviti ovaj parametar na E_ALL:

Na primjer, ako pokrenete sljedeći kod:

ini_set("pogreške_prikaza", 1);
ini_set("prijava_pogreški", E_SVE);

Primit ćemo pogreške dvije kategorije odjednom (obavijest i upozorenje):

Kada se koristi nedeklarisana varijabla, pojavljuje se pogreška E_NOTICE. Prilikom spajanja na bazu MySQL podaci(ili drugo) ne uspije - PHP tumač javlja pogrešku E_WARNING.

Pogreške u zapisivanju

Čak i ako je konfiguracijski parametar display_errors postavljen na 0, i dalje bi trebalo biti moguće vidjeti je li došlo do pogreške tijekom izvođenja skripte. Dakle, ako se dogodi greška, moramo znati gdje i zašto se dogodila. U te svrhe PHP ima postavke za bilježenje pogrešaka.

Standardno znači PHP jezik greške se nigdje ne bilježe. Da biste to promijenili, trebate promijeniti konfiguracijski parametar log_errors na 1 s 0:

ini_set("log_greški", 1);

U tom će slučaju pogreške automatski biti zapisane u datoteku navedenu u konfiguracijski parametar dnevnik_pogreški. Parametar error_log također se može promijeniti navođenjem staze do željene datoteke gdje će se pogreške bilježiti:

ini_set("reg_log", "/var/log/php_errors.log");

Dakle, za kod:

ini_set("pogreške_prikaza", 1);
ini_set("prijava_pogreški", E_SVE);
ini_set("log_greški", 1);
ini_set("reg_log", __DIR__ . "/log.txt");
$db = mysql_connect($db_host, "korisnik", "lozinka");

Slične informacije bilježe se u log datoteku i prikazuju na stranici:

PHP obavijest: Nedefinirana varijabla: db_host u Z:\home\test\www\index.php na retku 7
PHP upozorenje: mysql_connect(): pristup odbijen za korisnika "user"@"localhost" (koristeći lozinku: YES) u Z:\home\test\www\index.php na retku 7

Pogreške u rukovanju

Pogreške se dijele na ulovljive i neuhvatljive. Pogreške koje nisu kobne mogu se uhvatiti pomoću korisničkog koda. Stožerna tablica opisi kategorija pogrešaka otkrivaju informacije o tome koje se kategorije pogrešaka mogu uhvatiti.

Da biste uhvatili nekritične pogreške u kodu, dovoljno je implementirati i deklarirati vlastitu funkciju te proslijediti njezino ime funkciji set_error_handler. U ovom slučaju, 5 parametara se prosljeđuje implementiranoj funkciji:

  • razina pogreške kao cijeli broj;
  • poruka o pogrešci kao niz;
  • naziv datoteke u kojoj je došlo do greške, kao niz;
  • broj retka u kojem se pojavila greška, kao cijeli broj;
  • niz svih varijabli koje postoje u opsegu gdje je došlo do pogreške. Štoviše, bit će uključene i globalne varijable.
,

Zaključak

PHP ima moćne alate za rukovanje i upravljanje standardnim širenjem pogrešaka. Stoga neće biti teško uhvatiti ovu ili onu pogrešku, pod uvjetom da je skripta ispravno konfigurirana. Poznavanje ovog područja sastavni je dio svakog PHP programera, budući da puno koda koristi gore opisani mehanizam


Često sam čuo o ovom problemu od drugih korisnika. Neki, zbog hostera, trebaju sakriti greške koje se pojavljuju, drugi, naprotiv, moraju razumjeti što se događa s njihovim kodom, jer se ne prikazuje niti jedna greška. U ovom ću članku pokušati prikazati sve glavne načine prikazivanja/skrivanja pogrešaka.

U PHP skripti1) Postoji samo jedan operator u PHP-u koji podržava sustav upravljanja greškama - znak @. Omogućuje vam da zanemarite bilo koju poruku o pogrešci. Mora se staviti ISPRED izraza koji ga može sadržavati.

U primjeru postoji namjerna pogreška, ali NEĆE biti prikazana

$vrijednost = @$var[$ključ];
2) Također možete umetnuti postavku za parametar prikaza pogreške (display_errors) prije provjere PHP skripte. Može imati vrijednost On (prikaži) ili Off (sakrij).

Ini_set("display_errors","On");
error_reporting("E_ALL");
I u skladu s tim, nakon koda koji je provjeren za pogreške, vratite parametar natrag.

Ini_set("prikaz_pogreški","Isključeno");

Na primjer, želite vidjeti pogreške u skripti

Ini_set("display_errors", "On"); // prikazat će se poruke o pogrešci
javljanje_pogreške(E_SVE); // E_ALL - prikaz SVE greške
$vrijednost = $var[$ključ]; // primjer pogreške
ini_set("prikaz_pogreški", "Isključeno"); // sada neće biti poruka
Možete ga postaviti obrnuto (isključeno na vrhu i uključeno na dnu) tako da se pogreške NE prikazuju u određenom dijelu koda.

U datoteci .htaccess Najčešće se problem rješava određivanjem postavki u datoteci .htaccess koja se nalazi u korijenskom direktoriju web mjesta. U retku php_flag display_errors također trebate postaviti On ili Off

Php_flag display_errors Uključeno
#pokaži sve pogreške osim upozorenja (Napomena)
php_value error_reporting "E_ALL & ~E_NOTICE"

U datoteci php.ini Kao što vidite, parametar se može specificirati na nekoliko mjesta. Međutim, ako želite da ovaj parametar ima određenu vrijednost na cijelom web mjestu, lakše ga je postaviti u datoteci php.ini (možda neće uvijek biti dostupna na hostingu), ali u ovom slučaju možete čak i zaobići postavke cjelokupnog hostinga

U php.ini:

Prijava_pogreške = E_SVE
display_errors Uključeno
U Gornji red Selektiramo sve vrste grešaka, a na dnu dajemo zeleno svjetlo za njihov prikaz.

Nakon uređivanja morate ponovno pokrenuti Apache kako bi se postavke promijenile i stupile na snagu (graciozno ili ponovno pokretanje):

Sudo apachectl -k graciozan

Kojim redoslijedom se obrađuje parametar pogreške?Na samom početku se uzima u obzir parametar php.ini, zatim .htaccess, a zatim ono što je navedeno izravno u PHP skripti. Dakle, ako nešto ne radi, potražite lanac, možda tamo postoji drugačija postavka.

Kao i uvijek, hvala na pažnji i sretno! Nadam se da je članak bio koristan!

    Namjeran:

    • print, echo i druge funkcije koje proizvode izlaz
    • Neobrađeni odjeljci prethodni

      Ako je izvor pogreške naveden kao zatvoren?> onda je ovdje ispisan tekst koji nedostaje ili je neobrađen. Oznaka završetka PHP-a ne prekida izvršenje skripte u ovom trenutku. Svi znakovi teksta/razmaka nakon što su dosad ispisani kao sadržaj stranice.

      Općenito je prihvaćeno, osobito među početnicima, da se zadnje ?> PHP oznake za zatvaranje trebaju izostaviti. Time se sprječava mali dio ovih slučajeva. (Češće su krivci include()d skripte.)

    • Izvor pogreške naveden kao "Nepoznato u retku 0"

      Obično je to PHP proširenje ili php.ini ako je izvor pogrešaka specifičan.

      • Ponekad je opcija konfiguracije toka gzip ili ob_gzhandler.
      • Ali to može biti bilo koji modul dvaput učitan extension= koji generira implicitnu PHP poruku o pokretanju/upozorenju.
    • Prethodne poruke o grešci

      Ako drugi operater ili PHP izraz uzrokuje ispis upozorenja ili obavijesti, što se također smatra prijevremenim izlazom.

      U tom slučaju trebate izbjeći pogrešku, odgoditi izvršenje naredbe ili, na primjer, potisnuti poruku. isset() ili @() - kada ni jedno ne sprječava kasnije otklanjanje pogrešaka.

    Nema poruke o grešci

    Ako imate error_reporting ili display_errors onemogućene u php.ini tada se upozorenje neće pojaviti. Ali ignoriranje pogrešaka neće daleko odvesti problem. Zaglavlja se i dalje ne mogu poslati nakon ranog odlaska.

    Stoga, kada se zaglavlje("Lokacija: ...") preusmjerava tiho, preporučuje se praćenje upozorenja. Odredite ih s dvije jednostavne naredbe za pozivanje skripte:

    Izvještavanje_pogreški(E_ALL); ini_set("pogreške_prikaza", 1);

    Ili set_error_handler("var_dump"); , ako sve drugo ne uspije.

    Kada govorimo o preusmjeravanju zaglavlja, često biste trebali koristiti idiom poput ovog za staze konačnog koda:

    Izlaz(header("Lokacija: /finished.html"));

    Po mogućnosti čak i pomoćnu funkciju koja ispisuje korisničku poruku ako header() ne uspije.

    Izlazna memorija kao zaobilazno rješenje

    Može sakriti razmak za HTML izlaz. Ali čim aplikacija logično pokuša poslati binarni sadržaj (kao što je generirana slika), vanjski izlaz u međuspremniku postaje problem. (Potreban je ob_clean() kao prethodna opcija.)

    Međuspremnik je ograničene veličine i može se lako preliti ako se ostavi na zadanim postavkama. I to nije neuobičajeno, teško je pratiti kada se to događa.

    Oba pristupa mogu postati nepouzdani - osobito pri prebacivanju između razvojnih i/ili proizvodnih poslužitelja. To je razlog zašto se izlazni međuspremnik općenito smatra samo štakom/striktnim rješenjem.

    Ova se poruka o pogrešci pokreće kada se bilo što pošalje prije slanja HTTP zaglavlja (sa setcookiejem ili zaglavljem). Uobičajeni razlozi za ispis nečega prije HTTP zaglavlja:

      Nasumični razmaci, često na početku ili kraju datoteka, na primjer:

    Da biste to izbjegli, samo ga ostavite zatvorenim?>

    • Vrijednosti bajtova su bajtovi na početku php datoteke. Proučite svoje php datoteke pomoću hex editor da sazna je li to slučaj. Moraju započeti bajtovima 3F 3C. Možete sigurno ukloniti EF BB BF specifikaciju s početka datoteka.
    • Eksplicitni izlaz, kao što su pozivi na echo, printf, readfile, passthru, kod prije PROVJERITE PRAZNE RAZMAKE TAKOĐER OVDJE; OVAJ RED (prazan red) NE SMIJE POSTOJATI.

      Većinu vremena ovo bi trebalo riješiti vaš problem. Provjerite sve datoteke povezane s datotekom koja vam je potrebna.

      Bilješka. Ponekad EDITOR (IDE), kao što je gedit (standardni uređivač Linuxa), dodaje jedan prazan red u datoteku za spremanje. Ovo se ne bi smjelo dogoditi. Ako koristite linux. možete koristiti VI editor za uklanjanje razmaka/redova nakon ?> na kraju stranice.

      Ako vam se ovo ne sviđa, možete koristiti ob_start za međuspremnik izlaza, kao što je prikazano u nastavku:

      Moguće rješenje 2:

      Ovo će spremiti izlaz u međuspremnik i vaša će se zaglavlja stvoriti nakon što se stranica spremi u međuspremnik.

      Umjesto retka ispod

      //header("Lokacija:".ADMIN_URL."/index.php");

      pisati

      Echo("location.href = "".ADMIN_URL."/index.php?msg=$msg";");

      ?>