service container truc?

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 3 volgende »

Ozzie PHP

Ozzie PHP

01/10/2013 23:29:49
Quote Anchor link
He guys,

Wie durft even mee te denken?

Een tijdje terug heb ik een vraag gesteld over het nut van exceptions. Oké, goed. Het lijkt me nu wel wat om exceptions te gaan gebruiken, maaar...

Ik werk dus met een service container waarin ik ook wat gegevens van een website opsla, bijv. de naam en de url. Stel nu dat ik ga werken met exceptions, dan zou ik die gegevens (naam van de website en de url) willen loggen. Op die manier kan ik dus zien op welke url er een exception wordt getriggerd. Waar het nu om gaat, hoe krijg ik die gegevens vanuit de service container in de exception class??? Klein voorbeeldje (totaal niet kloppend, maar het gaat enkel even om het idee!):

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 Core {

  private $container;

  public function __construct() {
    $this->container->getWebsiteData()->setName(); // stop de naam van de website in de container
    $this->container->getWebsiteData()->setUrl(); // stop de URL van de website in de container
  }

  public function foo() {
    if ($er_gaat_iets_fout) {
      throw new Exception('Je doet iets verkeerd!');
    }
  }

}

?>

Oké, even een stom voorbeeldje dus... maar waar het om gaat is dat in de function foo een exception wordt gegooid. Hoe kan die exception nu de informatie verkrijgen die in de container zit? Ja... zullen jullie zeggen... doe dan zoiets:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
throw new Exception('Je doet iets verkeerd!', $this->container);

Maar dat wil ik niet, want dan moet ik overal waar ik een exception wil gooien die container gaan meegeven. Dan sla ik volgens mij de plank mis. Ik vraag me dus af of er een andere handige manier is, waardoor die exception toch aan het container object kan komen. Het enige wat ik me zou kunnen bedenken is een singleton gebruiken voor de container, maar het gebruik van singletons wordt afgeraden. Wie heeft een ideetje?
 
PHP hulp

PHP hulp

26/04/2024 18:54:35
 
Wouter J

Wouter J

01/10/2013 23:35:04
Quote Anchor link
nee, niet mogelijk.
 
Ozzie PHP

Ozzie PHP

01/10/2013 23:35:58
Quote Anchor link
Thanks Wouter. Daar was ik al bang voor. Dan toch een singleton gebruiken?
 
Wouter J

Wouter J

01/10/2013 23:46:28
Quote Anchor link
Nee, exception moet helemaal niks hiervan af weten. Exception gaat om de foutmelding, de exception logger moet van deze container variabelen afweten. En dat kan je wel gewoon normaal doen.
 
Ozzie PHP

Ozzie PHP

01/10/2013 23:49:13
Quote Anchor link
Dankjewel Wouter. Aleen begrijp ik niet wat je bedoelt :-/

Ik gooi een Exception... vanuit die exception wordt een loggen aangeroepen denk ik dan? Maar hoe weet die logger dan van de container variabelen? Dan heb je toch weer hetzelfde probleem?
 
Wouter J

Wouter J

01/10/2013 23:50:57
Quote Anchor link
Nee, die exception logt niks. De gene die de exception opvangt (de exception handler) logt de exception. En die handler is gewoon een klasse waarvan een service gemaakt kan worden.
 
Ozzie PHP

Ozzie PHP

01/10/2013 23:55:09
Quote Anchor link
Wouter, jouw technische kennis gaat verder dan de mijne en ik probeer je echt te begrijpen....

Zoals jij het zegt, zou ik zoiets denken...

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
if ('...') {
  throw new MyException();
}


class MyException {

  public function __construct() {
    // log de error, inclusief gegevens uit de service container
  }

}

?>

Waar ga ik de fout in?
 
Wouter J

Wouter J

01/10/2013 23:59:40
Quote Anchor link
Dat een exception alleen data vast houdt en je pas in de catch bepaalt wat je met die data doet, bijv. het loggen

Toevoeging op 01/10/2013 23:59:40:

Dat een exception alleen data vast houdt en je pas in de catch bepaalt wat je met die data doet, bijv. het loggen
 
Ozzie PHP

Ozzie PHP

02/10/2013 00:02:53
Quote Anchor link
Zou je misschien een heel klein voorbeeldje daarvan kunnen geven zodat ik het principe begrijp? (mag ook morgen als dat beter uitkomt)

Kan dit trouwens:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if ('...') {
  throw new MyException();
}

?>

Of moet je een exception altijd in een try-catch blok zetten?
 
Wouter J

Wouter J

02/10/2013 00:09:08
Quote Anchor link
Gooi exceptions waar je wilt! :)

Voorbeeldje:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
// bootstrap file of service config
$excephandler = new ExceptionHandler($container->get('logger'));
$excephandler->setUrl($container->get('site.url'));

try {
  throw new \Exception('fool! Do it correct');
}
catch (\Exception $e) {
  $excephandler->handle($e);
}

?>


Of gebruik set_exception_handler
 
Ozzie PHP

Ozzie PHP

02/10/2013 00:19:59
Quote Anchor link
Ah, op zo'n fiets. Dat maakt het een stuk duidelijker, thanks :)))
Tot zover is het dan duidelijk!

Misschien kun je me dan ook nog iets anders uitleggen... (maar dat mag ook morgen!)

1) Wanneer moet ik een try/catch blok ergens omheen zetten, en wanneer een if statement?
2) Hoe zorg ik dat bij een ernstige fout de applicatie compleet stopt (bijvoorbeeld indien er geen database connectie tot stand kan komen), maar dat ie bij een minder ernstige fout (bijv. een user die een getal invoert ipv een string) de applicatie gewoon doorgaat, maar er uitsluitend een error wordt gelogd?

Hmmm, nog eentje dan... de laatste...

3) Stel dat ik ergens bestanden moet inladen (dit zijn gewoon "vaste" bestanden) via require, moet ik daar dan ook een try/catch blok (of if-statement) omheen zetten, of gaat dat te ver?

Alvast bedankt!
 
Wouter J

Wouter J

02/10/2013 01:05:22
Quote Anchor link
1) hoe wil je exceptions catchen met een if statement?
2) ernstige fout: exception nergens opvangen en laten afhandelen door de set_exception_handler (die pas wordt aangeroepen als de exception nergens wordt gevangen)
minder ernstige fout: exception wel opvangen en er iets leuks mee doen
3) doe wat je wilt, zelf gebruik ik bijna nergens try..catch blocken
 
Ozzie PHP

Ozzie PHP

02/10/2013 01:12:34
Quote Anchor link
Hmm, (voor mij) lastig onderwerp dit.

Ik kan me herinneren dat jij allerlei verschillende exceptions kan gooien in je code, maar hoe doe je dat dan? Stel ik wil input valideren (of iets een int is). Gebruik je dan telkens een try/catch blok?

Kun je dan niet een exception in een if-statement gooien, en dat die exception ergens anders in een try/catch blok wordt opgevangen?

(ik ben ff de weg nu kwijt... )
 
Wouter J

Wouter J

02/10/2013 01:15:51
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if (!is_int($someVar)) {
    throw new \UnexpectedValueException('$someVar needs to be an int, ... given');
}

?>
 
Ozzie PHP

Ozzie PHP

02/10/2013 01:19:15
Quote Anchor link
Ja precies, maar dat is dus wat ik bedoelde...

Ozzie PHP op 02/10/2013 00:19:59:
1) Wanneer moet ik een try/catch blok ergens omheen zetten, en wanneer een if statement?

Wouter J op 02/10/2013 01:05:22:
1) hoe wil je exceptions catchen met een if statement?

Ik snap'm even niet. Jij zegt dat je ze niet kunt vangen in een if-statement, maar je gebruikt in jouw voorbeeld zelf ook een if-statement? What am I missing?
 
Wouter J

Wouter J

02/10/2013 01:25:12
Quote Anchor link
Throw = gooien
Catch = vangen

Ik gebruik een if en daarna gooi ik een exception. Vervolgens wordt deze ergens anders in een try..catch block gevangen
 
Ozzie PHP

Ozzie PHP

02/10/2013 01:28:10
Quote Anchor link
Oké, ik begin het te begrijpen :)

Heb jij dan (ergens in je core) een heel groot try/catch blok om je code heen staan die alle exceptions afvangt?
 
Wouter J

Wouter J

02/10/2013 07:51:41
Quote Anchor link
Nee, die handel ik af met de exceptionhandler.
 
Ward van der Put
Moderator

Ward van der Put

02/10/2013 08:39:23
Quote Anchor link
Volgens mij had ik het eerder al eens aangekaart, maar er zijn twee exception-kerken. De ene kerk gelooft dat exceptions uitsluitend voor foutafhandeling kunnen worden gebruikt. De andere kerk vertrouwt ruimer op exceptions voor flow control, zoals constrolestructuren met if/elseif/else of switch/case/default.

Bij een try/catch wordt daadwerkelijk andere PHP-code uitgevoerd. Het lijkt op een if/else met een exception als de trigger voor de else:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php
try {
    throw new Exception;
    echo 'Deze code wordt niet uitgevoerd.';
}
catch (Exception $e) {
    echo 'Exception afgevangen.';
}

?>


Een exception hoeft niet per se een fout te zijn: het is letterlijk meer een uitzondering. Je kunt exceptions bovendien gebruiken om fouten op te lossen — wat vaak beter is dan fouten alleen maar melden.

Neem bijvoorbeeld deze invulling van een business rule. Hier wordt een fout niet slechts gemeld, maar meteen verholpen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php
try {
    if ($aantal > 5) {
        throw new Exception('Maximaal 5 per klant.');
    }
}
catch (Exception $e) {
    $aantal = 5;
}

?>


Verder ben je niet beperkt tot één exception, maar kun je een hele stack met exceptions bouwen. Dat kan bijvoorbeeld volgens een hiërarchische logica:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
// Klasse speciaal voor wiskundige fouten
class MathException extends Exception {}
// Not a number (NaN) is een vorm van een wiskundige fout
class NaNException extends MathException {}
?>


Verder kun je klassen ook nog hun eigen exceptions meegeven. Dan heb je bijvoorbeeld één exception-klasse voor een compleet project plus een tweede exception-klasse voor het databasegebeuren binnen het project:

• class FooCore_Exception extends Exception {}
• class FooCore_Database_Exception extends FooCore_Exception {}

En een namespace-indeling die er zo uitziet:

• ../library/FooCore/Exception.php
• ../library/FooCore/Database/Exception.php
 
Ozzie PHP

Ozzie PHP

02/10/2013 09:09:20
Quote Anchor link
Wouter J op 02/10/2013 01:25:12:
Ik gebruik een if en daarna gooi ik een exception. Vervolgens wordt deze ergens anders in een try..catch block gevangen

Wouter J op 02/10/2013 07:51:41:
Nee, die handel ik af met de exceptionhandler.

Euh, gebruik je dan én een exceptionhandler én try/catch blokken?

@Ward: thanks. Wat ik me afvraag... volgens Wouter doe je het loggen niet vanuit een Exception class, maar bepaal je in het catch-blok of er iets gelogd moet worden. Waarom zou je dan verschillende types exceptions gebruiken? In een tutorial zag ik dat je bijv. in een MathException zou kunnen zetten "Er is een wiskundige fout opgetreden:".

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if ('er is een wiskundige fout...') {
  throw new MathException('er mogen geen negatieve getallen worden gebruikt.');
}

?>

De uiteindelijke erorrmelding zou dan bijv. worden:
EXCEPTION: Er is een wiskundige fout opgetreden: er mogen geen negatieve getallen worden gebruikt.

En bij bijv. een verkeerde input fout zou je kunnen zeggen:
EXCEPTION: Er is verkeerde input geconstateerd: telefoonnummer mag geen letters bevatten.

Zoals je ziet is het enige dat verschilt de omschrijving van het soort fout. Maar moet je daar dan allerlei verschillende exception classes voor maken?
Gewijzigd op 02/10/2013 09:09:49 door Ozzie PHP
 
Ward van der Put
Moderator

Ward van der Put

02/10/2013 09:51:37
Quote Anchor link
Als alleen de tekst van de foutmelding varieert, heb je niet eens exceptions nodig. In plaats van een throw new Exception('Oeps') die eindigt in een uncaught exception met de melding 'Oeps' kun je dan evengoed een trigger_error('Oeps') gebruiken.

Het draait voor een deel om verantwoordelijkheden. Zoals wel vaker bij OOP. In jouw voorbeeld van een MathException meld je de fout, maar doe je er niets mee.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
if ($getal < 0) {
    throw new MathException('Er mogen geen negatieve getallen worden gebruikt.');
}

?>


Je hebt een beslissingsregel geformaliseerd (hier geen negatieve getallen), maar je toezicht op die regel blijft beperkt tot mopperen over fouten. Je kunt er echter ook voor kiezen om de afgevangen fout te verhelpen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php
try {
    if ($getal < 0) {
        throw new MathException('Er mogen geen negatieve getallen worden gebruikt.');
    }
}
catch (MathException $e) {
    $getal = abs($getal);
}
catch (Exception $e) {
    echo 'Er is een onbekende fout opgetreden.';
}

?>


Als je de MathException alleen verantwoordelijk wilt maken voor rekenwerk met getallen, en bijvoorbeeld niet voor inputfouten, krijg je zoiets:

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 {
    if (!is_numeric($getal)) {
        throw new Exception('Het argument is geen getal.');
    }

    if ($getal < 0) {
        throw new MathException('Er mogen geen negatieve getallen worden gebruikt.');
    }
}
catch (MathException $e) {
    $getal = abs($getal);
}
catch (Exception $e) {
    echo 'Er is een fout opgetreden. ' . $e->getMessage();
}

?>
 

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.