Hibakezelés (try-catch, throw new Exception) -konstrukotrban/destruktorban
Kezdek kiakadni a PHP-re, de nagyon:
Egy külön file-ból betöltött osztály konstruktorában felfedezett hibát szeretnék jelezni egy throw new Exception-nel az objektumot létrehozni akaró programrésznek.
Egyszerűen nem törődik vele, fut tovább, mintha mi sem történt volna...Kb. így néz ki a problémás rész (remélem, nem írtam el semmit - az eredeti kódot kiherélni kissé macerásnak tűnik)
A DB konstruktorában a try-catch blokk nem képes elkapni a Loggerben kiváltott Exception-t.
Az tiszta, hogy átírhatom a programot úgy, hogy a konstruktorokban ne legyen hibakezelést igénylő művelet, de ez megint egy olyan dolog, hogy akkor minek a konstruktor, ha nem automatizálhatom a tennivalókat, rajta keresztül?
Másik variáció, hogy a hibakezelést igénylő műveletek hibaága egy die-ban kell, hogy végződjön, ami megintcsak nem tetszik, de kényszermegoldásként lehet, hogy ezt fogom használni.
+1, a fentitől független, de már a tapétát kaparom, annyira nem értem:
Ennyi a file tartalma és azt bírja mondani, hogy "syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in"
Ezek után töröltem a file-t, újra beírtam a kommentek nélkül, most jó...
Ciki, hogy eredetileg úgy hoztam létre, hogy egy működő php file-t lemásoltam, kikommenteztem a tartalmát és elé írtam a fenti if... sort.
■ Egy külön file-ból betöltött osztály konstruktorában felfedezett hibát szeretnék jelezni egy throw new Exception-nel az objektumot létrehozni akaró programrésznek.
Egyszerűen nem törődik vele, fut tovább, mintha mi sem történt volna...
class DB {
protected $l;
function __construct(){
...
try {
$this->l=new Logger("logdir/log.txt");
$this->l->put("uzenet");
} catch (Exception $e){
---hibaüzenet megjelenítése---
}
}
class Logger {
protected $logfile;
function __construct($fil){ $this->logfile=$fil; }
private function writeLog($uz){
if(!$f=fopen($this->logfile,"a")){ throw new Exception("Hiba"); }
...
}
function put($uz){
$this->writeLog($uz);
}
}
A DB konstruktorában a try-catch blokk nem képes elkapni a Loggerben kiváltott Exception-t.
Az tiszta, hogy átírhatom a programot úgy, hogy a konstruktorokban ne legyen hibakezelést igénylő művelet, de ez megint egy olyan dolog, hogy akkor minek a konstruktor, ha nem automatizálhatom a tennivalókat, rajta keresztül?
Másik variáció, hogy a hibakezelést igénylő műveletek hibaága egy die-ban kell, hogy végződjön, ami megintcsak nem tetszik, de kényszermegoldásként lehet, hogy ezt fogom használni.
+1, a fentitől független, de már a tapétát kaparom, annyira nem értem:
<?php
if(!defined('XXXX')){ exit; }
/*...
több soros, kikommentezett szakasz
*/
?>
if(!defined('XXXX')){ exit; }
/*...
több soros, kikommentezett szakasz
*/
?>
Ennyi a file tartalma és azt bírja mondani, hogy "syntax error, unexpected T_CONSTANT_ENCAPSED_STRING in"
Ezek után töröltem a file-t, újra beírtam a kommentek nélkül, most jó...
Ciki, hogy eredetileg úgy hoztam létre, hogy egy működő php file-t lemásoltam, kikommenteztem a tartalmát és elé írtam a fenti if... sort.
try/catch
Köszi, ettől tartottam.
Akkor tényleg marad amit írtam, hogy vagy die v. nem a konstruktorban csinálom a hibalehetőséggel bíró műveleteket.
A másik: vi-t használok, nem látszott rajta, hogy gond lenne a file-lal. A végén, kínomban már töröltem is a kód maradékát, csak az if(!defined... maradt benne, de úgy is pofázott. Ezzel kellőképp felbosszantott, töröltem, újra beírtam, most megy. Kapjabe... :-)
(ilyenkor bezzeg nem teszem el törlés előtt a git-be, nehogy vissza tudjam hozni... :-( )
Szvsz semmi gond nincs a
Így van, egyszerűen elnéztem
Viszont furcsa, hogy senkinek sem tűnt fel: amire panaszkodtam, az egy try-catch blokkban lévő exception, aminek ebben a formában működnie kellene. Gondot a kezeletlen exception okozna azzal, hogy megszakítja a konstruktor futását->nem tud korrekt módon felépülni az objektum, de ilyesmiről szó sem volt. (és szerencsére működik is)
Miért?
Ezzel nem értek egyet. Miért ne lehetne kivételt dobni konstruktorból? Van mondjuk egy fájlt beolvasó konstruktorunk. Eléggé nonszensz lenne, ha nem dobhatnánk onnan kivételt.
A fenti kódban ami inkább kifogásolható az a kivétel lekezelése. Ugyan az egyetemen azt tanítják, hogy minden kivételt le kell kezelni - amivel egy cseppet sem akarok vitatkozni - azonban azt nem tanítják meg, hogy hol. Pl. az adatbázis-kezelő rétegnek nem biztos, hogy kellene foglalkoznia üzenetek megjelenítésével.
A nagy könyv azt írja, hogy
A fenti kód csak egy az eredeti alapján összetákolt példa volt, mert azt hittem, hogy a konstruktorban lévő catch nem tudja elkapni a try blokkban létrehozott és felhasznált objektum által kiváltott exception-t. Utóbb kiderült, hogy ez nem igaz, nem onnan jöttek a hibaüzenetek.
Az üzenet megjelenítéséről csak annyit: ez az egész arról szólt volna, hogy az adatbáziskezelővel kapcsolatot tartó osztály logolja a saját működését és ehhez egy már elkészült, log író osztály egy példányát használtam fel.
(hangsúlyozom: tanulom a PHP-t és az objektum orientált "tervezést", az egész pusztán arra kellett, hogy később vissza tudjam keresni, melyik programrész mit művelt, merre járt)
Keress másik könyvet :)
Ez a félkész objektum meg csalóka. A legtöbb nyelvben mire a konstruktorok kezdenek futni, nyelv szempontjából maga az objektum létezik, hiszen le van neki foglalva a memória és be van neki állítva a típusa. Logikailag nekünk ugyan még nincs kész, hiszen nincsen a mi értelmezésünk szerint alapállapotba állítva. Viszont előfordulhat olyan eset, hogy ez nem teljesíthető, ilyenkor dobunk kivételt. Ilyenkor logikailag valóban nem lesz "kész" az osztály, azonban a kivétellel egyértelműen jeleztük, hogy ez egy selejt osztály, nem biztos, hogy használni kellene, sőt inkább el kellene takarítani (ha a nyelv nem tenné meg automatikusan).
Öt perce bányásztam elő a
Destruktorban nem illik, mert azonnal Fatányéros... izé... fatal error lesz az eredmény, de a konstruktorra nincs megkötés. (sajnos/szerencsére nem találom az eredeti forrásomat :) )
Félkész objektum: ettől kezdve természetesen az is hülyeség volt. Egyébként ha abortálom a konstruktort, akkor nem ad értéket a "new" mellett, az = bal oldalán álló változónak, ergo nem is jön létre az objektum.
Hát ez a no comment kategória...
Onnan is maceráltam volna a logot és akkor jött a kezeletlen és kezelhetetlen hiba. Hogy miért, arról csak sejtéseim vannak: destruktorban már nem lehet számítani az objektum által korábban létrehozott változókra/objektumokra... (bár így sem teljesen tiszta, mert a hibaüzenet szerint nem éri el a használandó logfile-t, holott maga a file elérhető, hiszen pár sorral korábban még írt bele és a log file nevét sem felejtette még el)
destruktorba se
Konstruktorral (talan, de itt
Destruktorral jobb, ha nem
Átalában. De én most tanulom
De én most tanulom a PHP-t, kipróbálok mindent, még azt is, amit elvileg nem lenne szabad, mert csak olvasással nem lehet tanulni. ;-)
Jó persze. Annyit kell tudni
Keverem a Java-val? Mintha
Mintha azt olvastam volna, hogy a változók, objektumok stb. állapota nem meghatározható, nem azt, hogy el lettek takarítva. (ezt csak a "precizitás" kedvéért... ;-) )
Jóvanna :D Majd jöhetsz
Ha megfizeted... más munkát
:D :D :D
Sajnos ennyire nem vicces a
Mellesleg: szopatom magam, mint a torkosborz, hogy át tudjam írni a PDO és a PDOStatement execute metódusát, mert az SQL hibákat szeretném Exception-ként viszontlátni, erre... PDO::setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION) és máris minden szép... :D
A beépített
Adapter alatt nem t'om, mit
Gyártottam egy osztályt, extends PDO-val, aztán sokáig gondolkodtam, hogy lehetne kulturáltan elérni, hogy pl. a prepare ne PDOStatement objektumot adjon vissza, hanem egy olyat, amit én írtam és a PDOStatement leszármazottja. Mire ma megtaláltam, hogy a setAttribute-tal el tudom érni, addigra azt is felfedeztem, hogy Exception-t is lehet kérni, ha valami hiba történik a mysql-ben. :D
Adapter pattern
Hát csinálsz egy
Jééé... eltűnt, amit erre válaszoltam...
Azzal amit írsz, egy gond van: a PDO néhány metódusa, pl. a prepare v. a query egy-egy PDOStatement osztályú objektumot ad vissza. Ahhoz, hogy ezt úgy cseréljem le, ahogy te javasoltad, felül kellene írnom a PDO megfelelő metódusait egyesével, hogy azok a megfelelő objektum típust adják vissza.
Szóval vagy nem fogtam fel amit írtál vagy ez a módszer célravezetőbb jelen esetben.
Jó, csak a te kedvedért
PDO.prepare(blah)
példányosít egy PDOStatement-et, aztán annak a metódusaival beállítja rajta a paramétereket. Neked meg ezt a részt kéne újraírnod a saját osztályodban. Ebben az esetben teljesen használható, amit írtam...szerk:
A PDOStatement leírásában nincs bent a __construct. Az SQL, a PDO objektum, meg a többi paraméter átadása meg valszeg constructor injectionnel megy, szóval ha lehetséges a PDO-tól függetlenül példányosítani a PDOStatement-et, akkor meg lehet csinálni, amit írtam. Ezt leírás hiányában úgy lehet tesztelni, hogy megpróbálod példányosítani, aztán ha valamelyik paramétert hiányolja, akkor sikítani fog miatta, ha meg egyáltalán nem lehet így példányosítani, akkor meg arról szóló hibaüzenetet kapsz, vagy fatal errort, vagy hasonló szépséget.
A prepare egy a sok közül,
Persze mindez már csak merőben elméleti dolog, mivel ami miatt felül akartam írni a PDOStatement egyes részeit, az megoldódott azzal, hogy a PDO tud exceptiont visszadobni, ha hibába botlik. :)
Ahm. Az alap hibát ott
Nem, az alapvető hibát ott
(sikeresen eldugták, a setAttribute metódus leírását leszámítva, nyomát sem találtam ennek a lehetőségnek )
A hibakezelés az a dolog,
Vajon miért? :DDD