service container truc?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: « vorige 1 2 3 volgende »

NOLot -

NOLot -

02/10/2013 10:03:16
Quote Anchor link
Goede uitleg Ward! Als je exceptions niet helemaal begrijpt kun je ook eens gaan spelen met Java (de programmeertaal). php is niet echt een taal waar excepties voorop staan, bij java wordt echter om de haverklap een exceptie gegooid als iets niet klopt
 
PHP hulp

PHP hulp

27/05/2026 07:01:58
 
Ozzie PHP

Ozzie PHP

02/10/2013 10:04:26
Quote Anchor link
Dankjewel voor je uitgebreide uitleg Ward!

Roept ook wel weer een paar vragen op. Dat try/catch blok, kun je dat ook overkoepelend maken? Of moet ik bij iedere input validatie dan een try/catch blok gebruiken? Kan ik bijv. op 1 plek al die verschillende catch-es instellen?

In jouw voorbeeld maak jij van $getal een positief getal, maar geef je dan ook nog een foutmelding naar de gebruiker, en zo ja... hoe? Echo je dan hardcoded een melding vanuit het catch-gedeelte?
 
NOLot -

NOLot -

02/10/2013 10:09:01
Quote Anchor link
Overkoepelend kan niet, dan moet je gewoon meerdere excepties vangen. Foutmelding naar de gebruiker doe je door middel van het bericht

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
throw new NaNException(sprintf('Het argument "%s" is geen getal.', $getal));
 
Ozzie PHP

Ozzie PHP

02/10/2013 10:42:31
Quote Anchor link
@NOLot: ik bedoel... moet je overal telkens een try/catch blok gaan plaatsen, of kun je in feite je hele applicatie tussen een try/catch blok zetten?

Stel ik heb 50 classes waarin ik input van de gebruiker wil valideren. Moet ik dan ook 50 keer een try/catch blok maken? Is dat de bedoeling? Of maak ik 1 keer een try/catch blok en zorg ik dat al die 50 classes hierbinnen vallen?

Ik snap wat je bedoelt met de foutmelding naar de gebruiker, maar op welke plek echo je die foutmelding? Doe je dat vanuit het catch-blok? Ik kan me voorstellen dat een foutmelding een bepaalde css meekrijgt. Krijg je dan zoiets:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
try {

}
catch (Exception $e) {
  echo '<span class="exception">' . $e->getMessage() . '</span>';
}

?>

Is dat de bedoeling?
Gewijzigd op 02/10/2013 10:43:21 door Ozzie PHP
 
Ward van der Put
Moderator

Ward van der Put

02/10/2013 11:01:09
Quote Anchor link
Je kunt inderdaad alle reguliere code in één try zetten en de uitzonderingen in aparte exceptions afhandelen.

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
<?php
try {
    /********************************************
     * In deze try gaan we                      *
     * - input verwerken,                       *
     * - daarmee een berekening uitvoeren en    *
     * - het resultaat opslaan in een database. *
     ********************************************/


} catch (InputException $e) {

}
catch (MathException $e) {

}
catch (DatabaseException $e) {
    
}
catch (Exception $e) {
    
}

?>


Maar vroeg of laat zul je zien dat deze code te veel doet. Ik zou er vooral geen hele applicatie in stoppen met 50 klassen. Zoiets als de DatabaseException in dit voorbeeld kun je prima elders onderbrengen.

Foutmeldingen voor de gebruiker toon je alleen als de gebruiker het probleem kan verhelpen. Dat is een van de redenen om daarvoor een aparte Exception-klasse toe te voegen.
 
NOLot -

NOLot -

02/10/2013 11:07:48
Quote Anchor link
Nee niet echt. Als ik het goed begrijp wil je excepties op een nette manier laten zien. Dan moet je je excepties niet afzonderlijk gaan catchen, maar gewoon laten gaan (dus zonder een try catch blok). Een manier om ze dan op te vangen is bijvoorbeeld om je hele applicatie een try catch neer te zetten die alles opvangt.

Gelukkig heeft php daar ook al iets voor, de set_exception_handler die alle excepties opvangt die niet opgevangen worden in een catch blok. Op die manier kan je gewoon overal excepties gooien, en kun je in de handler er iets leuks mee doen.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
set_exception_handler(function($e) {
    echo '<span class="exception">' . $e->getMessage() . '</span>';
});

throw new RuntimeException('boom');
 
Ozzie PHP

Ozzie PHP

02/10/2013 11:32:51
Quote Anchor link
@Ward: oké. Dan zou ik juist zeggen dat het handig is om alles in 1 try te zetten met diverse catches. Dan heb je alles bij elkaar staan en hoef je dus nooit een try ergens omheen te zetten. Dat is toch juist handig? Of zie ik iets over het hoofd dan? En maakt het eigenlijk iets uit in welke volgorde je de catch-blokken zet? In jouw voorbeeld: InputException, MathException, DatabaseException, Exception. Maar mag dat bijvoorbeeld ook zijn: MathException, Exception, InputException, DatabaseException?

@NOLot: ik zou niet voor alle exceptions een foutmelding aan de gebruiker willen geven (denk ik nu), maar bijv. bij een verkeerde user input kan ik me voorstellen dat je aangeeft dat de gebruiker een getal moet intypen ipv een string. Dan zou je dus per catch-blok moeten aangeven of er iets moet worden ge-echoot. Ik vind het alleen raar/onnatuurlijk om iets te echoën in een catch-blok. Ik echo liever iets in een view, maar dat kan op deze manier dus niet?
 
NOLot -

NOLot -

02/10/2013 11:43:29
Quote Anchor link
Bij input validatie kan je wel een try catch blok gebruiken denk ik. Dat zijn weer hele andere type exceptions. Zoiets zou je dan kunnen doen:

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
<?php

try {
    $validator->validate($user);
}
catch(ValidationException $e) {
    $errors[] = $e->getMessage();
}


if (count($errors) != 0) {
    // return view met $errors
} else {
    $user->save();
}

?>


Zelf gebruik ik excepties nooit op die manier, maar meer om programmeer problemen tegen te gaan
 
Ozzie PHP

Ozzie PHP

02/10/2013 11:53:09
Quote Anchor link
Pfff, tis wel lastig zo :-( Ik snap wat jij doet, maar het maakt het er niet echt makkelijker op. Maar goed, de "normale" manier van het tonen van een message aan de bezoeker is dus via een echo in het catch-gedeelte?
 
NOLot -

NOLot -

02/10/2013 14:40:57
Quote Anchor link
Lol nee toch juist niet. Zie mijn voorbeeld hierboven, ik echo toch helemaal niks... Volgens mij probeer je excepties te begrijpen op een specifieke situatie die alleen jij begrijpt. Zorg eerst eens dat je excepties echt goed begrijpt, google dan exceptions best practice of iets dergelijks.

Vergeet niet dat php niet echt een exception friendly taal is. In andere talen kun je (op syntax errors na) ALLE errors afvangen met een try catch, in php niet.

Hoe oud ben je eigenlijk ozzie?
 
Ozzie PHP

Ozzie PHP

02/10/2013 14:52:21
Quote Anchor link
Ik snap wat je bedoelt, maar ik probeer vooral te begrijpen hoe en wanneer je exceptions moet afvangen.

Voorheen werkte ik gewoon met if-jes en elsejes. Maar nu wil ik dus eens met exceptions gaan werken. Ik snap dat het voordelen heeft, en nu wil ik weten hoe ik het op de juiste manier moet implementeren.

Even weer het voorbeeldje van Ward (iets aangepast)... stel ik zet dit in de core/kernel class:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
try {
    // Hier gaan we de complete request afhandelen.
} catch (InputException $e) {

}
catch (MathException $e) {

}
catch (DatabaseException $e) {
    
}
catch (Exception $e) {
    
}

?>

Nu hoef ik maar 1x een try en catch in te stellen. Stel nu dat ik in class Foo een InputException wil gooien, dan komt ie in de try/catch van de core/kernel terecht. Is dat een optie? Of gaat de code dan ook niet meer verder in die Foo class?

Offtopic:

"Hoe oud ben je eigenlijk ozzie?"

Privé vragen graag via PM :)))
 
NOLot -

NOLot -

02/10/2013 15:16:24
Quote Anchor link
Ozzie PHP op 02/10/2013 14:52:21:
Ik snap wat je bedoelt, maar ik probeer vooral te begrijpen hoe en wanneer je exceptions moet afvangen.

Voorheen werkte ik gewoon met if-jes en elsejes. Maar nu wil ik dus eens met exceptions gaan werken. Ik snap dat het voordelen heeft, en nu wil ik weten hoe ik het op de juiste manier moet implementeren.

Even weer het voorbeeldje van Ward (iets aangepast)... stel ik zet dit in de core/kernel class:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
try {
    // Hier gaan we de complete request afhandelen.
} catch (InputException $e) {

}
catch (MathException $e) {

}
catch (DatabaseException $e) {
    
}
catch (Exception $e) {
    
}

?>

Nu hoef ik maar 1x een try en catch in te stellen. Stel nu dat ik in class Foo een InputException wil gooien, dan komt ie in de try/catch van de core/kernel terecht. Is dat een optie? Of gaat de code dan ook niet meer verder in die Foo class?


Als jij in je Foo class een exceptie gooit, en hem niet daarbinnen opvangt, crasht je code net zolang totdat je bij de eerstvolgende exception vanger komt. Als dat dan toevallig in de kernel class is, zal hij daar in komen.

Dat is zeker een optie, kijk maar eens naar een HttpKernel implementatie van symfony: https://github.com/symfony/HttpKernel/blob/master/HttpKernel.php#L63
 
Ward van der Put
Moderator

Ward van der Put

02/10/2013 15:21:35
Quote Anchor link
Je kunt dat op verschillende manieren doen. De eerste variant is, inderdaad zoals je zegt, een exception werpen en aan de core/kernel overlaten wat ermee gebeurt.

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
<?php
class Foo
{
    public function __construct()
    {


        // Hier gaat het ergens fout
        throw new Input_Exception('Oeps');
    }
}


// Core/kernel
try {
    $foo = new Foo();
}
catch (Input_Exception $e) {
    $errors[] = $e->getMessage();
}
catch (Exception $e) {
    $errors[] = $e->getMessage();
}

?>


Je kunt een deel van de verantwoordelijkheid echter ook delegeren naar de klasse die de exception genereert. Dan heb je dezelfde core/kernel als hierboven, maar wordt de klasse:

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
<?php
class Foo
{
    public function __construct()
    {

        try {
            // Hier gaat het ergens fout
            throw new Input_Exception('Oeps');
        }
catch (Input_Exception $e) {
            // Hier proberen we het probleem op te lossen.
            // Als dat niet lukt, spelen we de exception door.

            if ($probleem_is_niet_opgelost) {
                throw $e;
            }
        }
    }
}

?>


Het kan dus beide, want je kunt exceptions doorgeven.
 
Ozzie PHP

Ozzie PHP

02/10/2013 16:25:43
Quote Anchor link
Ah oké, thanks. Stel nu dat we uitgaan van de 1e situatie. De exception wordt dan opgevangen in de core/kernel. Waar gaat de code dan vervolgens verder? Stopt de code in het catch-blok in de kernel?

Stel, iemand voert een int in ipv een string. Ik wil dan een melding tonen, maar de rest van de code wil ik wel nog laten uitvoeren. Dus de errormelding moet in beeld komen, maar daaronder moet het formulier weer tevoorschijn komen. Kan dat gewoon? Of stopt de code zodra ie in een catch-blok komt?
 
Ward van der Put
Moderator

Ward van der Put

02/10/2013 16:32:23
Quote Anchor link
De code wordt gewoon volledig uitgevoerd. Je kunt de catch immers gebruiken om in te grijpen, dus in dat opzicht lijkt een try/catch op een if/else.

In de catch van een Input_Exception, zoals in het voorbeeld, kun je dus een foutmelding opstellen via $e->getMessage() en die daarna ergens anders in een view stoppen.
 
Ozzie PHP

Ozzie PHP

02/10/2013 16:44:39
Quote Anchor link
Dat klinkt goed Ward.. ik snap 'm alleen (nog) niet.

Jouw voorbeeld:

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
<?php
class Foo
{
    public function __construct()
    {


        // Hier gaat het ergens fout
        throw new Input_Exception('Oeps');
    }
}


// Core/kernel
try {
    $foo = new Foo();
}
catch (Input_Exception $e) {
    $errors[] = $e->getMessage();
}
catch (Exception $e) {
    $errors[] = $e->getMessage();
}

?>

Hoe kan ik hier dan in het catch-gedeelte de foutmelding opvangen en weer teruggeven aan de Foo class?
 
NOLot -

NOLot -

02/10/2013 16:47:45
Quote Anchor link
Dat kan niet, dan moet je hem in de Foo class zelf opvangen
 
Wouter J

Wouter J

02/10/2013 16:49:17
Quote Anchor link
Oké, even wat Exception basix:

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
<?php

try {
  echo 'hé, mij zie je!';

  throw new \Exception('Berichtje...');

  echo 'hè, ik wordt niet eens meer uitgevoerd...';
}
catch (\Exception $e) {
  echo 'Ikke wordt uitgevoerd';

  $logger->log($e, Logger::LEVEL_ERROR);

  echo 'En ikke ook!';
}

echo 'Ikke ook!';
?>


Als er in de constructor van Foo dus een exception wordt gegooid zal deze klasse niet worden aangemaakt. Stel ik heb geen try catch blokken, dan zal mijn hele applicatie stoppen. Maar dat wil ik niet, ik wil dat hij dan even dit overslaat maar het contact formulier weer geeft. Daar plaats ik een try catch blok om het aanmaken van deze klasse, de rest heeft er dan geen last van.

Zodra er iets fout gaat in een klasse kun je natuurlijk niet meer terug naar de klasse, er ging immers iets fout...
 
NOLot -

NOLot -

02/10/2013 16:51:23
Quote Anchor link
Ozzie probeer zelf ook eens wat he ;) Schrijf wat code en kijk wat er uit komt (mijn advies om eens naar Java te kijken om je globale programmeer niveau omhoog te halen staat nog steeds)
 
Ozzie PHP

Ozzie PHP

02/10/2013 16:58:15
Quote Anchor link
@NOLot: ik programmeer geen Java. Als je het niet erg vindt dan ga ik daar ook niet aan beginnen... :-/

@Wouter: kijk, da's een duidelijke uitleg! Maar dat zou dus betekenen, dat als ik een InputException in de kernel opvang, dat de overige code dus ook niet meer wordt uitgevoerd. En als er dan onder het try/catch blok in de kernel geen code meer staat, dan houdt het script dus gewoon op. Correct? Dus wat ik dacht te kunnen doen, kan dus niet.

Ward van der Put op 02/10/2013 16:32:23:
In de catch van een Input_Exception, zoals in het voorbeeld, kun je dus een foutmelding opstellen via $e->getMessage() en die daarna ergens anders in een view stoppen.

Ward gaat er hier dan vanuit dat de view pas "onder" het try/catch blok in de kernel wordt aangeroepen zodat de foutmelding uit de catch aan de view kan worden doorgegeven?
 

Pagina: « vorige 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.