Exceptions gebruiken
Weer een vraagje over het gebruik van Exceptions, doe het nu alvolgt?
Is het niet overbodig om van elke publieke methode ( functie ) alle invoer te controleren dmv Exceptions?
Code (php)
Gewijzigd op 01/01/1970 01:00:00 door Thijs X
Edit:
Niet goed gekeken.
Volgens mij hoort het zo:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Test
{
public function __construct($sNaam)
{
if (empty($sNaam) || !is_string($sNaam))
{
throw new Exception('Parameters zijn onjuist.');
}
// doe je ding
}
}
try
{
$oTest = new Test(123);
// doe je ding met $oTest
}
catch (Exception $e)
{
echo '<p class="error"><strong>Error:</strong><br />' . $e->getMessage . '</p>';
}
?>
class Test
{
public function __construct($sNaam)
{
if (empty($sNaam) || !is_string($sNaam))
{
throw new Exception('Parameters zijn onjuist.');
}
// doe je ding
}
}
try
{
$oTest = new Test(123);
// doe je ding met $oTest
}
catch (Exception $e)
{
echo '<p class="error"><strong>Error:</strong><br />' . $e->getMessage . '</p>';
}
?>
Gewijzigd op 01/01/1970 01:00:00 door - -
Ja ben bezig met een Formulier klasse, en heb de die() wel nodig anders word het formulier alsnog half geprint met de onderdelen die wel goed zijn ingvuld.
Maar het maakt debuggen van (anders niet gevonden fouten) echt zoveel sneller, dat ik het toch erg sterk kan aanraden.
Bedankt voor julllie reacties, ik ga de fouthandeling wel in de classe zelf verwerken omdat het idd ook voor andere mensen makkelijk bruikbaar moet zijn. Als hij af is post ik hem misschien hie rwel op PHPhulp
De fout-opmerking in de klasse zelf. Het afhandelen (een alternatieve route verzinnen, die() is daar (niet?) een van) is niet de taak van je klasse over het algemeen. Dus alleen throw. Catch hoef je binnen een klasse zelden te gebruiken. Tenzij je natuurlijk een fout op dat moment kan afhandelen, dus een alternatief kan bieden.
Maar als ik een formulie wil gaan aanmaken met mn klasse en ik vul verkeerde parameters in, dan wil ik natuurlijk niet dat het formulier wel word weergegeven, dan wil ik een nette error.
Of simpeler gezegd: op de plek waar je het meeste op kan vangen en toch nog wat nuttigs er mee kan doen, en dus uiteindelijk het minste try-blokken (het mooiste is natuurlijk om maar 1 enkel try-blok nodig te hebben) nodig hebt.
maar pas een try/catch te gebruiken als ik een nieuw formulier aanmaak?
Echter, als je het hebt over een formulier genereren, dan neem ik aan dat je er ook een soort van controle inbakt die de opgestuurde waarden controleert. De vraag is, wil je hier wel exceptions voor gebruiken? Het lijkt mij handiger om hier gewoon boolean waarden voor te gebruiken bij de controle ($this->field->isValid($waarde)) en om eerlijk te zijn kan ik zo ook niet een situatie bedenken waarin je werkelijk een try/catch-blok nodig zal hebben in je formulier-klasse zelf.
Als ik het goed begrijp dan gebruik je dus geen exceptions in een klasse?
Ik gebruik nu catch in mijn construtor bij het aan maken van een object.. is dat wel volgens de regels of moet ik deze catch pas toepassen als ik het alle objecten aan maak?
Hopelijk snap je een beetje wat ik bedoel..
Onderstaande code is van mijn lijst klassen die een ftp object aan maakt..
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
function __construct($p_SubDir=''){
try{
if ($this->m_SourceType == 'ftp'){
if(!empty($this->m_FtpHost) AND !empty($this->m_FtpUserName) AND !empty($this->m_FtpUserPass)){
$this->obj_FTP = new clsFtp($this->m_FtpHost,$this->m_FtpUserName,$this->m_FtpUserPass);
if(!empty($p_SubDir) AND $p_SubDir != '' ){
$this->obj_FTP->setCurrentDir($this->m_FtpDocRoot . $p_SubDir);
}else{
$this->obj_FTP->setCurrentDir($this->m_FtpDocRoot);
}
}else{
throw new constructException('Ftp hostname or credentials are missing');
}
}elseif($this->m_SourceType == 'http' ){
return $this->m_HttpRootPath;
}else{
throw new constructException('No Source type has been set!');
}
} catch (constructException $e){
print $e->Report();
exit;
}
} // End fucntion __construct()
?>
function __construct($p_SubDir=''){
try{
if ($this->m_SourceType == 'ftp'){
if(!empty($this->m_FtpHost) AND !empty($this->m_FtpUserName) AND !empty($this->m_FtpUserPass)){
$this->obj_FTP = new clsFtp($this->m_FtpHost,$this->m_FtpUserName,$this->m_FtpUserPass);
if(!empty($p_SubDir) AND $p_SubDir != '' ){
$this->obj_FTP->setCurrentDir($this->m_FtpDocRoot . $p_SubDir);
}else{
$this->obj_FTP->setCurrentDir($this->m_FtpDocRoot);
}
}else{
throw new constructException('Ftp hostname or credentials are missing');
}
}elseif($this->m_SourceType == 'http' ){
return $this->m_HttpRootPath;
}else{
throw new constructException('No Source type has been set!');
}
} catch (constructException $e){
print $e->Report();
exit;
}
} // End fucntion __construct()
?>
Gewijzigd op 01/01/1970 01:00:00 door Andreas Warnaar
Stel dat je een (stel) klasse hebt die data beheert met behulp van een database die hij zelf onderhoudt. Nu wil je een klompje data opslaan, en de klasse probeert een insert uit te voeren. Dus je past een eigenschap aan, en roept indirect __set aan. __set roept een updateDatabase-method aan. Bummer! Tabel bestaat niet, en er wordt een exception gegooid door PDO. updateDatabase kan niets met die exception, want updateDatabase is slechts verantwoordelijk voor het bijwerken van de database, niet voor het aanmaken. __set weet echter wel raad met het probleem, en vangt de exception op - in dit geval de PDOException - en roept de createDatabase method aan, waarna hij alsnog de updateDatabase method een keer probeert. Stel nu dat je __set een array meegeeft terwijl je property een string als type verwacht. __set bemoeit zich daar vandaag niet zo mee, updateDatabase controleert daar wel op en gooit een InvalidArgumentException. Tja, __set weet niet wat hij met zo'n exception moet. PDOExceptions kan hij deels goed afhandelen, maar deze weet hij geen raadt mee en vangt hij dus ook niet op.
Moraal van het verhaal: Exceptions vang je pas op wanneer je een alternatief hebt. Anders laat je ze verder vallen.
Dus, in jouw code zet je wel de throw, maar niet de catch. print $e->report & exit zijn niet een alternatief - het is niet aan de klasse om foutmeldingen te printen of de applicatie te stoppen, dat is aan de applicatie zelf. Klassen zijn niets meer dan een hulpmiddel en moeten zich niet met andere zaken bemoeien. Dus je zet je try-catch statement om het aanmaken van de instantie heen, en niet binnen de constructor.
Verder vind ik de eigen exception niet zo netjes. constructException zegt niets over de oorzaak van het probleem, maar alleen waar het probleem is opgetreden. Dat kan je ook wel zien aan de getLine() en getFile() methods van de exception. Je hebt daar echter niet veel aan bij het opvangen. Uit mijn vorige voorbeeld: een updateDatabaseException die gegooid is omdat de database niet bereikbaar is is toch degelijk anders dan een updateDatabaseException omdat de up te daten data niet geldig is. Voor beiden is een andere oplossing, dus voor beiden kan je een ander catch-blok gebruiken. Maar een catch-blok maakt onderscheidt tussen exceptions op basis van hun klasse, en die is hetzelfde. Dus moet je in je catch-blok nu op iets anders gaan controleren.
Probeer je in eerste instantie te beperken tot de exceptions die SPL meebrengt: http://devzone.zend.com/article/2565-The-Standard-PHP-Library-SPL#table1. Ik heb zelden een eigen exception nodig, bijna alle mogelijke "fouten" zijn op te delen in deze 6 exceptions.
Overigens, in je constructor doe je iets op basis van de eigenschap m_SourceType**, alsof hij voordat __construct aangeroepen wordt handmatig geset kan worden. Wel, helaas, bij mijn weten wordt zodra je een object aanmaakt als eerst de constructor aangeroepen, met uitzonderen van FETCH_OBJ i.c.m. PDO. Hetzelfde voor de username & password. Ow, en return in een constructor heeft geen zin, de constructor zal altijd de instantie zelf teruggeven. Tenzij je hem natuurlijk als static method aanroept, maar dan krijg je weer gezeur over dat $this niet bestaat.
** Waarom ingodsnaam die m_ ervoor, als er $this-> voor staat is het toch hoe dan ook een member-variabele, domme Hongaarse notatie...
Gewijzigd op 01/01/1970 01:00:00 door Jelmer -
Gewijzigd op 01/01/1970 01:00:00 door Andreas Warnaar
-