Try ... catch en do while
Ik zit al een tijdje met een paar vragen. Ik weet een hele hoop over PHP (en dingen die daarmee te maken hebben) en over Java ook de basis dingen.
Nu snap ik een paar dingen niet. Om te beginnen de try ... catch functie.
Wat kun je hier precies mee? Ik heb begrepen dat dit is om fouten af te vangen, maar dit kun je toch ook gewoon met een if-statement doen, of denk ik hier verkeerd?
M'n andere vraag is, wanneer je nou precies een do while gebruikt.
Ik weet wanneer ik een for en while moet gebruiken en hoe ze werken, ook van do while. Toch snap ik niet waarom deze functie bestaat, op school is me verteld dat het soms handig kan zijn, maar er waren toen geen voorbeelden gegeven.
Hebben jullie antwoord op m'n vragen? Thanks :)
Een functie kan op meerdere manieren aangeven dat er iets fout is gegaan. Zo kan je bijvoorbeeld false teruggeven. Je kan dan met een if/else constructie dit afvangen. Het kan ook zijn dat de functie een exceptie geeft. Dit kan je niet afvangen met een if/else constructie aangezien de exceptie optreedt voordat de functie iets returnt. Je krijgt dan ook de foutmelding "Uncaught Exception: ..." met de exceptie erbij. Je wil natuurlijk niet graag dat een gebruiker een dergelijke PHP foutmelding voor zijn neus krijgt. Als je (net als in een if/else constructie) deze fout goed wilt afhandelen dan kan je hem afvangen met een try ... catch blok.
Voorbeeld:
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
class Links {
private $baseUrl;
public function __construct() {
$this->$baseUrl = 'http://test.com';
}
/**
* Generating normal URLs (like index.php?page=5)
*
* @param int $page
* @param string $linkname
* @return string
*/
public function generateLink($page, $linkname) {
if(is_numeric($page)) {
return '<a href="' . $this->baseUrl . '?page=$page">' . $linkname . '</a>';
} else {
throw new Exception("Parameter 'page' must be an integer.", E_ERROR);
}
}
}
?>
class Links {
private $baseUrl;
public function __construct() {
$this->$baseUrl = 'http://test.com';
}
/**
* Generating normal URLs (like index.php?page=5)
*
* @param int $page
* @param string $linkname
* @return string
*/
public function generateLink($page, $linkname) {
if(is_numeric($page)) {
return '<a href="' . $this->baseUrl . '?page=$page">' . $linkname . '</a>';
} else {
throw new Exception("Parameter 'page' must be an integer.", E_ERROR);
}
}
}
?>
Dit is een klasse puur bedoeld als voorbeeld. De functie genereert een URL gebaseerd op een paginanummer en de linknaam. Hier moet je dus met een try/catch blok de exceptie afvangen.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
$paginate = new Paginate();
try {
$paginate->generateLink(1, 'De eerste pagina'); //Dit gaat goed.
$paginate->generateLink('fout', 'Test'); //Dit levert een exceptie op.
$paginate->generateLink(3, 'De derde pagina'); //Dit wordt niet meer uitgevoerd want als er een exceptie optreedt dan gaat ie meteen naar de catch.
} catch(Exception $e) {
echo 'Woeps er is iets fout gegaan. Het bericht is' . $e->getMessage();
echo 'Start de foutafhandeling!';
}
?>
$paginate = new Paginate();
try {
$paginate->generateLink(1, 'De eerste pagina'); //Dit gaat goed.
$paginate->generateLink('fout', 'Test'); //Dit levert een exceptie op.
$paginate->generateLink(3, 'De derde pagina'); //Dit wordt niet meer uitgevoerd want als er een exceptie optreedt dan gaat ie meteen naar de catch.
} catch(Exception $e) {
echo 'Woeps er is iets fout gegaan. Het bericht is' . $e->getMessage();
echo 'Start de foutafhandeling!';
}
?>
Wanneer moet je wat gebruiken?
Gebruik false in return als het een normaal scenario is dat een bepaald iets niet goed is. Gebruik excepties bij onverwachte fouten die niet horen te gebeuren. Soms is het een beetje een grijs gebied wanneer je wat moet gebruiken.
Vanwege PHP's verleden worden de fouten die optreden niet als excepties 'gethrowed' maar krijg je gewoon een foutmelding die eventueel uit te schakelen is middels error reporting. Dat is waarom je try/catch niet veel ziet. Alleen nieuwe OO libraries van PHP gebruiken excepties zoals ze horen. Doordat PHP zelf niet goed met excepties omgaat gebruiken ook veel gebruikers excepties niet zoals ze in de meeste programmeertalen gebruikt worden. Zie http://php.net/manual/en/language.exceptions.php voor meer informatie.
Heb je misschien een voorbeeld van een situatie waarin een do while wél nuttig kan zijn?
Gewijzigd op 03/08/2011 17:05:28 door Roel -
Bump!
Code (php)
Hierdoor wordt de gast rol altijd toegevoegd aan de user. Weet alleen niet of de next constructie zo goed werkt. Maar zoals gezegd in de praktijk wordt hij niet veel gebruikt. Ik zie het overigens wel soms voorbij komen in Zend Framework.
In Java heb je trouwens ook nog try { } catch () { } finally { } om je aangemaakt resources e.d. in op te ruimen, dit heb je in PHP niet.
Ik snap precies hoe de functie werkt, maar ik kan er met m'n verstand niet bij waarom?
Dan moet je of de while conditie aanpassen of je maakt er een do while van en je laat de conditie hetzelfde.
Wanneer gebruik je het nu echt? Niet, eigenlijk. Je kan de conditie van de while eigenlijk altijd zo formuleren dat je het met een while afkan. Terwijl je een while altijd (0 tot * keer) kan gebruiken, is de do while vrij specifiek (1 tot * keer). Als je al code hebt die 1 tot * keer uitgevoerd moet worden dan schrijven mensen het uit gewenning vaak alsnog met while.
Bij een virusscanner of zo? Ik snap gewoon totaal niet waarom zo'n functie dan überhaupt bestaat.
PHPhulp, of PHPzwijg?
En letwel dat do while en try catch geen functies zijn, maar "semantieke constructies"
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
<?php
do
{
$uniek = een_of_andere_functie();
$query = mysql_query("SELECT id FROM tabel where veld = '".$uniek."'", $conn);
}
while(mysql_num_rows($query)); // do het nog een keer als er een rij gevonden is
// we zijn uit de do-while, dus deze code bestaat (hoogst waarschijnlijk, denk aan race condities) nog niet
mysql_query("INSERT into tabel (veld) VALUES ('".$uniek."')", $conn);
?>
do
{
$uniek = een_of_andere_functie();
$query = mysql_query("SELECT id FROM tabel where veld = '".$uniek."'", $conn);
}
while(mysql_num_rows($query)); // do het nog een keer als er een rij gevonden is
// we zijn uit de do-while, dus deze code bestaat (hoogst waarschijnlijk, denk aan race condities) nog niet
mysql_query("INSERT into tabel (veld) VALUES ('".$uniek."')", $conn);
?>
Thx voor je voorbeeld Dos.
Code (php)
Maar natuurlijk zijn er vele manieren om dit op te lossen.
Gewijzigd op 09/08/2011 16:15:52 door Eric Wagener
Toevoeging op 10/08/2011 09:51:01:
Zoals belooft een stukje code, ik heb even de hele functie gepakt zodat eventuele geintreseerde de context ook begrijpen :) Het is een frontcontroller plugin die het e.e.a. met navigatie doet :)
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
42
43
44
45
46
47
48
49
50
51
52
53
<?php
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$file = APPLICATION_PATH . '/configs/navigation.xml';
if (!file_exists($file)) {
throw new BestBuy_Exception('Navigation.xml not found in configs directory.');
}
$config = new Zend_Config_Xml($file, 'nav');
$navigation = new Zend_Navigation($config);
$this->_addClassToContainer('link', $navigation);
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$layout = $bootstrap->getResource('layout');
/**
* Uses Pike_Menu to check permissions based on more roles. (ZF 1.11 doesn't support
* multiple roles checking)
*
*/
$view = $layout->getView();
$view->navigation()
->PikeMenu($navigation)
->setACL(Zend_Registry::get('acl'))
->setRoles(Zend_Auth::getInstance()->getIdentity()->getRoles());
/**
* Check if the resource name of the current page has child pages and add these to
* the submenu. If it hasn't child pages look in has parent.
*/
$resource = implode('_', array(
$request->getModuleName(),
$request->getControllerName(),
$request->getActionName()
));
do {
$page = $navigation->findBy('resource', $resource);
if ($page instanceof Zend_Navigation_Page && $page->hasPages()) {
$view->submenu = $page;
} elseif($page instanceof Zend_Navigation_Page) {
$resource = $page->getParent()->resource;
if (null === $resource)
break;
} else {
break; //$page is null there is no submenu
}
} while ($view->submenu === null);
}
?>
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
$file = APPLICATION_PATH . '/configs/navigation.xml';
if (!file_exists($file)) {
throw new BestBuy_Exception('Navigation.xml not found in configs directory.');
}
$config = new Zend_Config_Xml($file, 'nav');
$navigation = new Zend_Navigation($config);
$this->_addClassToContainer('link', $navigation);
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$layout = $bootstrap->getResource('layout');
/**
* Uses Pike_Menu to check permissions based on more roles. (ZF 1.11 doesn't support
* multiple roles checking)
*
*/
$view = $layout->getView();
$view->navigation()
->PikeMenu($navigation)
->setACL(Zend_Registry::get('acl'))
->setRoles(Zend_Auth::getInstance()->getIdentity()->getRoles());
/**
* Check if the resource name of the current page has child pages and add these to
* the submenu. If it hasn't child pages look in has parent.
*/
$resource = implode('_', array(
$request->getModuleName(),
$request->getControllerName(),
$request->getActionName()
));
do {
$page = $navigation->findBy('resource', $resource);
if ($page instanceof Zend_Navigation_Page && $page->hasPages()) {
$view->submenu = $page;
} elseif($page instanceof Zend_Navigation_Page) {
$resource = $page->getParent()->resource;
if (null === $resource)
break;
} else {
break; //$page is null there is no submenu
}
} while ($view->submenu === null);
}
?>
Thx. Misschien een beetje een late reactie, maar ik had hem nog niet gelezen!