Kako omogućiti ili onemogućiti prikaz pogreške u PHP-u? Prethodne poruke o grešci
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
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 jezgrom | Ne |
64 | E_COMPILE_ERROR | Slično E_ERROR, ali generirano Zend Engineom | Ne |
128 | E_COMPILE_WARNING | Slično E_WARNING, ali generirano Zend Engineom | Ne |
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 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.
Php_flag display_errors Uključeno
#pokaži sve pogreške osim upozorenja (Napomena)
php_value error_reporting "E_ALL & ~E_NOTICE"
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!
- 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.
- 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:
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";");
?>
Namjeran:
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šenjeMož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?>