note 69730 added to language.exceptions

From: Date: Mon, 18 Sep 2006 13:45:30 +0000
Subject: note 69730 added to language.exceptions
Groups: php.notes 
Request: Send a blank email to php-notes+get-117285@lists.php.net to get a copy of this message
Summary: * use destructors to perform a cleanup in case of exception. PHP calls method __destruct() on instance of class when variable storing the instance goes out-of-scope (or gets unset). This works for function leave by Exception, aside of plain return. (same as for C++, AFAIK) aFunction() { $i = new LockerClass(); throw new MinorErrorEx('Warn user & perform some other activity'); // $i->__destruct() gets called before stack unwind begins, unlocking whatever get locked by new LockerClass(); return $bar; } (A lengthy) example: Let's say you need to perform a series of operaions on SQL database that should not get disrupted. You lock the tables: <?php function updateStuff() { DB::query('LOCK TABLES a, b, c WRITE'); /* some SQL Operations */ someFunction(); /* more SQL Operations */ DB::query('UNLOCK TABLES'); } ?> Now, let's supouse that someFunction() may throw an exception. This would leave us with the tables locked, as the second DB::query() will not get called. This pretty much will cause the next query to fail. You can do it like: <?php function updateStuff() { DB::query('LOCK TABLES a, b WRITE'); /* some SQL Operations */ try { someFunction(); } catch ( Exception $e ) { DB::query('UNLOCK TABLES'); throw $e; } /* more SQL Operations */ DB::query('UNLOCK TABLES') } ?> However, this is rather ugly as we get code duplication. And what if somebody later modifies updateStuff() function in a way it needs another step of cleanup, but forget to add it to catch () {}? Or when we have multiple things to be cleaned up, of which not all will be valid all the time? My solution using destructor: i create an instance of class DB holding a query unlocking tables which will be executed on destruction. <?php function updateStuff() { $SQLLocker = DB::locker( /*read lock list*/array('a', 'b'), /*write lock list*/array('b') ); /* some SQL Operations */ someFunction(); /* $SQLLocker gets destructed there if someFunction() throws an exception */ DB::query('UNLOCK TABLES'); /* other SQL Operations */ /* $SQLLocker gets destructed there if someFunction() does not throw an exception */ } class DB { function locker ( $read, $write ) { DB::query( /*locks*/); $ret = new DB; $ret->onDestruct = 'UNLOCK TABLES'; return $ret; } function _destructor() { if ( $this->onDestruct ) DB::query($this->onDestruct); } } ?> ---- Server IP: 83.64.128.68 Probable Submitter: 81.219.32.9 ---- Manual Page -- http://www.php.net/manual/en/language.exceptions.php Edit -- https://master.php.net/note/edit/69730 Del: integrated -- https://master.php.net/note/delete/69730/integrated Del: useless -- https://master.php.net/note/delete/69730/useless Del: bad code -- https://master.php.net/note/delete/69730/bad+code Del: spam -- https://master.php.net/note/delete/69730/spam Del: non-english -- https://master.php.net/note/delete/69730/non-english Del: in docs -- https://master.php.net/note/delete/69730/in+docs Del: other reasons-- https://master.php.net/note/delete/69730 Reject -- https://master.php.net/note/reject/69730 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#117285) next »