try... catch en @

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 3 volgende »

Ozzie PHP

Ozzie PHP

16/01/2012 08:44:04
Quote Anchor link
Hallo, ik heb 2 vraagjes.

1) Hoe gebruik je een try-catch blok? Zet je het try-catch blok alleen om het stukje code heen waar je daadwerkelijk een exception wilt gooien als het misgaat? Of kun je het try-catch blok ook om de complete code van je website heen zetten, zodat alles dus in het try-catch blok staat? De laatste optie is veel makkelijker omdat je dan niet telkens een try-catch blok hoeft te maken en je direct een exception kunt gooien. Alleen ik vraag me af of dit de juiste wijze is en of hier wellicht (performance?)nadelen aan zitten.

2) Je kunt een mogelijke foutmelding onderdrukken door @ voor de functie te zetten, bijvoorbeeld @fopen(). Nu vraag ik me af, als ik de errormeldingen uitschakel voor de gehele website, heeft dit dan hetzelfde effect als @?

Alvast bedankt voor de reacties.
 
PHP hulp

PHP hulp

01/12/2024 12:53:25
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 08:54:45
Quote Anchor link
Exceptions kunnen in je hele code gebruikt worden, en zelfs in je ingevoegde classes.
Daarom vind het het gewoon handig om aan het begin van je hele script met try te beginnen, waarna je aan het einde een catch plaatst.

PDO bijv. die gebruikt een PDO-exception. Die kan je als ik het goed heb opvangen in een normale exception:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
catch(Exception $e)
  {
  echo 'Foutmelding: ' .$e->getMessage();
  }


Maar ook e.v.t in een specifiekere catch:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
catch(PDOException $e)
  {
  echo 'Er trad een SQL probleem op: ' .$e->getMessage();
  }
Gewijzigd op 16/01/2012 08:57:17 door - Ariën -
 
Ozzie PHP

Ozzie PHP

16/01/2012 09:09:17
Quote Anchor link
Aar, thanks voor je snelle reactie. Als ik het goed begrijp zet jij dus eigenlijk je hele website in een try-catch blok? Dus:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
try {
  // hier alle code van je website
} catch (Exception $e) {

}

?>


Maar ik vraag me dus af of dit nog nadelige gevolgen heeft. Als je alles namelijk "evalueert" (try) zou dat dan niet vertragend werken?

Toevoeging op 16/01/2012 09:12:36:

Toevoeging: als je error_reporting uit zet, dan kun je toch nog wel gewoon exceptions throwen? Bijv. if(!fopen('bestand')) throw new Exception('kan bestand niet openen').
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 09:14:29
Quote Anchor link
Yes, en nee, het levert geen vertraging op. Pas als er een exception optreedt (al is dat 400 lijnen verwijderd van de try) zal die exception opgeroepen worden.

Ik ben wel benieuwd hoe je dit mooi kan implementeren in een MVC model, zonder dat je de index staat te vervuilen met try en catches.
 
Ozzie PHP

Ozzie PHP

16/01/2012 09:24:23
Quote Anchor link
"Pas als er een exception optreedt (al is dat 400 lijnen verwijderd van de try) zal die exception opgeroepen worden."

Ja, dat klopt. Maar ik denk (ik weet het niet zeker) dat hij nu wel alles wat in het try gedeelte staat gaat evalueren. Het lijkt me dat hij alle code gaat "tryen" omdat alles in het "try" gedeelte staat. Ik kan me voorstellen dat dit vertraging oplevert, maar wellicht zit ik er helemaal naast.

"Ik ben wel benieuwd hoe je dit mooi kan implementeren in een MVC model, zonder dat je de index staat te vervuilen met try en catches."

Als je alles in 1 try-catch blok zet, dan is dat niet heel moeilijk denk ik. Dan zou je gewoon een index maken met een try-catch blok en in de try zet je include 'index2.php' of iets dergelijks. Je index2.php (of hoe je het ook wil noemen) wordt dan je "echte" index en daar hoef je dan geen try-catch meer in te zetten.
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 09:30:32
Quote Anchor link
Ik geloof dat hij dat niet gaat evalueren. In het CRM waar ik vroeger aan werkte met 8 man, werd dit ook gedaan. En pas bij een exception zal het script stoppen en de catch aanroepen.

Misschien dat iemand het beter weet, maar dit is wat ik begrijp.

In mijn vraag over de implementatie ervan in het MVC-model gaat het mij er niet om hoe ik de try catch implementeer, of je ze nou nest of niet....
Het gaat erop hoe ik dit in de methods implementeer. Een bootstrap zou het beste kunnen zijn, lijkt me?

Als je met index.php en index2.php bezig bent, dan ben je niet echt met MVC bezig.
 
Wouter J

Wouter J

16/01/2012 09:43:57
Quote Anchor link
Het is goed om meerdere soorten Exceptions te scheiden. Dit scheiden kun je dan doen in het catch blok, 1 try blok is volgens mij wel goed. Alleen als je met dit scheiden gaat werken kun je het beter zo aanpakken dat de user errors op de juiste plek geechoed worden.

PHP heeft verschillende ingebouwde Exceptions, waarvan sommige child van elkaar zijn of parent. Daardoor kun je deze mooi uit elkaar halen. Alle Exceptions in PHP kun je hier vinden: http://www.php.net/~helly/php/ext/spl/classException.html

Je ziet dat het in 2 delen is opgesplitst:
1) LogicException
2) RuntimeException

Een LogicException is een exception met fouten in de code en een RuntimeException is een exception met fouten van de gebruiker.

Een voorbeeld hierbij:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php

class Registery
{
  protected static $values;

  public static function set( $label, $value )
  {

    if( isset(self::$values[$label]) )
      throw new InvalidArgumentException(sprintf('[%s] The label(%s) already exists', __CLASS__, $label));

    self::$values[$label] = $value;
  }

  public static function get( $label )
  {

    if( !isset(self::$values[$label]) )
      throw new InvalidArgumentException(sprintf('[%s] The label(%s) does not exists', __CLASS__, $label));

    return self::$label;
  }
}


try
{
  if( $_SERVER['REQUEST_METHOD'] == 'POST' )
  {

     if( !isset($_POST['name']) )
       throw new UnexpectedValueException('Je moet een naam invullen');
  }
}

catch( LogicException $e )
{

  // een program error
  error_log($e->getMessage()); // Iets meer informatie mag natuurlijk wel
}
catch( RuntimeException $e )
{

  // een user error
  echo $e->getMessage();
}

?>


Fouten onderdrukken met @ is nooit goed. Deze fouten verschijnen niet als je display_errors uit zet, want dan komt er geen 1 fout meer zichtbaar.
Gewijzigd op 16/01/2012 09:45:22 door Wouter J
 
Jelle -

Jelle -

16/01/2012 09:46:20
Quote Anchor link
Vergeet niet een mooie foutmelding pagina te geven die automatisch de exception naar je mailt :) (bij een PDO fout bijvoorbeeld)

Een mooie foutpagina die niet veel relevants aangeeft wanneer debug uit staan en mooi alle fout gerelateerde informatie weergeeft wanneer debug aanstaat.

Verder is try{}catch{} niet echt trager, het is meer dat je php aangeeft: als er nu een fout optreed ga je naar regel ... om het op te vangen.
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 09:52:09
Quote Anchor link
Dan vraag ik me af hoe de implementatie ervan het beste in een MVC model eruit zal zien?

De try-catch in de bootstrap? En een exception-method oproepen. Of hoort dit niet in de bootstrap?
 
Ozzie PHP

Ozzie PHP

16/01/2012 09:54:33
Quote Anchor link
@Wouter: Thanks voor je reactie. Waarom verschillende typen exceptions gebruiken in plaats van 1? Je kan toch in de message aangeven wat er fout gaat? Wat betreft onderdrukken met @... dat doe ik liever niet. Maar ik wil wel mijn foutmeldingen kunnen uitschakelen en ik wil ook niet dat ze ergens gelogd worden (tenzij in debug mode). Als ik dan display_errors en error_reporting op 0 zet, heb ik dan hetzelfde resultaat als wanneer ik @ voor een functie zet?

@Smur f: het is dus niet zo dat als je alles in een try-blok zet, dat ie dan telkens eerst iedere regel gaat evalueren of iets dergelijks? Er gebeurt dus eigenlijk pas iets op het moment dat ie ergens throw new Exception() tegenkomt. Begrijp ik het zo goed? Dus eigenlijk wat Aar ook zegt?

@Aar: hmmm, dat weet ik eigenlijk ook niet..
Gewijzigd op 16/01/2012 09:55:11 door Ozzie PHP
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 09:57:04
Quote Anchor link
Ozzie PHP op 16/01/2012 09:54:33:
@Wouter: Thanks voor je reactie. Waarom verschillende typen exceptions gebruiken in plaats van 1? Je kan toch in de message aangeven wat er fout gaat?

Het ligt eraan of je ze apart wilt afhandelen?

Misschien wil je exception van PDO juist mailen, of een specifiekere PDO foutmelding geven. Als je echt maar 1 exceptie-foutafhandeling wilt gebruiken. Dan gebruik je toch de normale Exception.
 
Wouter J

Wouter J

16/01/2012 10:01:34
Quote Anchor link
Ozzie PHP:
Als ik dan display_errors en error_reporting op 0 zet, heb ik dan hetzelfde resultaat als wanneer ik @ voor een functie zet?

Ja
Ozzie PHP:
Er gebeurt dus eigenlijk pas iets op het moment dat ie ergens throw new Exception() tegenkomt. Begrijp ik het zo goed? Dus eigenlijk wat Aar ook zegt?

Ja, PHP voert gewoon de code uit, zoals normaal. Alleen mocht hij een throw tegenkomen, wat als het goed is alleen bij fouten gebeurd, dan springt hij over naar de catch.
Ozzie PHP:
Thanks voor je reactie. Waarom verschillende typen exceptions gebruiken in plaats van 1? Je kan toch in de message aangeven wat er fout gaat?

Ik wil niet dat de gebruiker een melding krijgt dat de DB niet werkt. Ik wil dat deze gelogd wordt, zodat ik die in het admin panel o.i.d. kan weergeven.
Ik wil wel dat foutmeldingen als 'geen naam ingevuld' worden weergegeven aan de gebruiker, maar die hoef ik daarna niet meer te zien.

Daarom moet je onderscheid maken tussen runtime en logic exceptions, zodat je deze taken ook mooi kan scheiden.
 
Jelle -

Jelle -

16/01/2012 10:02:58
Quote Anchor link
Het is ook een stuk overzichtelijker als je verschillende soorten exceptions hebt, het hoeft alleen maar een andere naam te hebben dan kun je al beter onderscheidt maken. Dit geldt al helemaal als je exceptions voor het gros van je foutmeldingen (ook door de gebruiker gegenereerde) gaat gebruiken. Die exceptions wil je dichterbij de fout afhandeling en niet helemaal op web niveau zoals Wouter zegt.

Op het traagheid niveau, in principe werkt het volgens mij zo dat als er een exception optreed hij dan pas gaat kijken of er op het huidige niveau een catch is en anders verder opgooit.
 
Ozzie PHP

Ozzie PHP

16/01/2012 10:13:45
Quote Anchor link
Dankjulliewel allemaal. Het is me een stuk duidelijker allemaal. Nog 2 vragen:

1) "Ik wil wel dat foutmeldingen als 'geen naam ingevuld' worden weergegeven aan de gebruiker, maar die hoef ik daarna niet meer te zien." Gebruik jij voor dit soort dingen Exceptions? Ik dacht dat je exceptions alleen gebruikt bij hele kritische processen (bijv. database die niet werkt, bestand dat niet kan worden geopend e.d.)

2) De vraag van Aar vind ik ook interessant. "Dan vraag ik me af hoe de implementatie ervan het beste in een MVC model eruit zal zien? De try-catch in de bootstrap? En een exception-method oproepen. Of hoort dit niet in de bootstrap?"
 
Wouter J

Wouter J

16/01/2012 10:15:41
Quote Anchor link
1) Ja, exceptions is voor elke vorm van foutafhandeling. In elk geval, zo gebruik ik het ik weet niet wat de correcte manier is.
2) Hier heb ik helaas geen verstand van...
 
Ozzie PHP

Ozzie PHP

16/01/2012 10:25:26
Quote Anchor link
Wouter, wat betreft punt 1... ik dacht dat de code stopt als je een Exception gooit. Of zit ik er nu naast? Maar als iemand z'n naam niet invult en de code stopt, dan wordt de view toch ook niet getoond?
 
Jelle -

Jelle -

16/01/2012 10:44:19
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
 echo 'dit werkt';
 try{
   echo 'dit ook';
   throw new Exception();
   echo 'dit niet';
 }
catch(Exception $e){
   echo 'en ditte wel weer';
 }

 echo 'en hier kom ik ook omdat de exception mooi opgevangen is';
?>


Je zou het zeg maar kunnen zien dat als je de exception niet goed opvangt, je try catch die om je site hangt hem opvangt en dan is dus de hele handel een try. In dat geval stopt inderdaad de code op het moment van de exception.

Even een voorbeeldje ter illustratie:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

    function test1(){
        throw new TrollException();
        echo 'hier komen we niet';
    }

    function
test2(){
        try{
            test1();
        }
catch(TrollException $e){
            echo 'opgevangen in test2';
        }

        echo 'hier dus wel';
    }

    try{
        test2();
        echo 'hier alleen als de exception in test2 al afgehandeld is';
    }
catch(Exception $e){
        echo 'hoge exceptions vangen veel wind';
    }

?>


Ik hoop dat het wat duidelijk maakt :)
Gewijzigd op 16/01/2012 10:45:31 door Jelle -
 
Ozzie PHP

Ozzie PHP

16/01/2012 10:54:14
Quote Anchor link
Ah, dat maakt het een stuk duidelijker :)
Maar dat betekent dus dat als je een try-catch om je hele code heen zet, dat dan je view niet wordt getoond (omdat er na het catch blok niks meer komt). Als je dus gebruikersfouten met try-catch wil afvangen, dan zou je dus telkens kleine try-catch blokjes moeten gebruiken, maar het lijkt me dan handiger om gewoon if-else te gebruiken toch?
 
- Ariën  -
Beheerder

- Ariën -

16/01/2012 11:00:45
Quote Anchor link
je kan toch één try-blok gebruiken, met meerdere catches achter elkaar, als je meerdere exceptions hebt. De eerste exception waar het script tegen aanloopt, zal dan worden getoond.
Gewijzigd op 16/01/2012 11:01:40 door - Ariën -
 
Jelle -

Jelle -

16/01/2012 11:04:10
Quote Anchor link
Dat ligt er maar net aan hoe jij de applicatie opbouwd, als jij de formulieren met if/elsen gaat controleren is een $formErrors = array() misschien handig. Maar als jij een $form->validate() (bijvoorbeeld) gebruikt kan die heel mooi een exception gooien met een melding, dan heb je de foutafhandeling mooi gescheiden.
 
Ozzie PHP

Ozzie PHP

16/01/2012 11:31:54
Quote Anchor link
Oké, dus je bedoelt bijvoorbeeld zoiets:

$mail = 'smurf@@@phphulp.nl';
$form->validate($mail);
toView($mail);
showView('mail_sent.php');

In dit geval is het mailadres verkeerd. Die validate functie zou dan een Exception throwen, maaaaar... hoe komt ie dan vervolgens weer bij toView() en showView() terecht? Of gaat ie daar gewoon verder na het throwen van de Exception?
 

Pagina: 1 2 3 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.