note 69730 added to language.exceptions
| From: | dexen at google dot me dot up | 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