finally again

php.internals

Cristiano Duarte

22 years ago
Hi internals ! I came into a problem when writing an IDL to PHP5 language mapping specification and an IDL to PHP5 language compiler. I'm using the community OpenORB IDL-to-Java compiler as a base for writing the IDL-to-PHP5 compiler, in fact, it is a translation from Java to PHP5. Everything is ok except the "finally" clause wich doesn't exists in Zend Engine 2. I know that many of you think that "finally" is useless but consider this case, and if anyone have a simple and elegant solution without implementing "finally" I'll be glad to listen. The code would be like this if we had finally: <? ... $_input = null; try { $_output = $this->_request('bind',true); org__omg__CosNaming__NameHelper::write($_output,$n); $_output->write_Object($obj); $_input = $this->_invoke($_output); return; } catch(org__omg__CORBA__portable__RemarshalException $_exception) { continue; } catch(org__omg__CORBA__portable__ApplicationException $_exception) { $_exception_id = $_exception->getId(); if ($_exception_id == org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { throw org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception-
>getInputStream());
} if ($_exception_id == org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { throw org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_excep tion->getInputStream()); } if ($_exception_id == org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { throw org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_excepti on->getInputStream()); } if ($_exception_id == org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { throw org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_except ion->getInputStream()); } throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception: $_exception_id"); } catch(Exception $_exception) { throw $_exception; } finally { $this->_releaseReply($_input); } ... ?> Since we don't have finally, the current code is: <? ... $_input = null; try { $_output = $this->_request('bind',true); org__omg__CosNaming__NameHelper::write($_output,$n); $_output->write_Object($obj); $_input = $this->_invoke($_output); $this->_releaseReply($_input); //PHP still does not have FINALLY !!! return; } catch(org__omg__CORBA__portable__RemarshalException $_exception) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! continue; } catch(org__omg__CORBA__portable__ApplicationException $_exception) { $_exception_id = $_exception->getId(); if ($_exception_id == org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception-
>getInputStream());
} if ($_exception_id == org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_excep tion->getInputStream()); } if ($_exception_id == org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_excepti on->getInputStream()); } if ($_exception_id == org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_except ion->getInputStream()); } $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception: $_exception_id"); } catch(Exception $_exception) { $this->_releaseReply($_input); //PHP still does not have FINALLY !!! throw $_exception; } $this->_releaseReply($_input); //PHP still does not have FINALLY !!! ... ?> IMHO, I think that replicating the finally code at the end of every catch block, before every throw/return statement and at the end of the try/catch statement justify the need of "finally". If there is another aproach without "finally" and without code redundancy, I really need it. Best Regards, Cristiano Duarte

Cristiano Duarte

22 years ago
> IMHO, I think that replicating the finally code at the end of every catch > block, before every throw/return statement and at the end of the try/catch > statement justify the need of "finally".
My mistake, it's not necessary to replicate the code at the end of every catch block. And I forgot to mention that there must be one "catch all" clause(wich is impossible in PHP) with a copy of the finally code and a rethrowing exception statement otherwise an exception that is not caugh will propagate without executing the replicated code of "finally". Cristiano Duarte

Cristiano Duarte

22 years ago
> Hi internals ! > > I came into a problem when writing an IDL to PHP5 language mapping > specification and an IDL to PHP5 language compiler. I'm using the
community
> OpenORB IDL-to-Java compiler as a base for writing the IDL-to-PHP5
compiler,
> in fact, it is a translation from Java to PHP5. Everything is ok except
the
> "finally" clause wich doesn't exists in Zend Engine 2. I know that many of > you think that "finally" is useless but consider this case, and if anyone > have a simple and elegant solution without implementing "finally" I'll be > glad to listen. > The code would be like this if we had finally: > <? > ... > $_input = null; > try { > $_output = $this->_request('bind',true); > org__omg__CosNaming__NameHelper::write($_output,$n); > $_output->write_Object($obj); > $_input = $this->_invoke($_output); > return; > } catch(org__omg__CORBA__portable__RemarshalException $_exception) { > continue; > } catch(org__omg__CORBA__portable__ApplicationException $_exception) { > $_exception_id = $_exception->getId(); > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { > throw >
org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception-
> >getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { > throw >
org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_excep
> tion->getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { > throw >
org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_excepti
> on->getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { > throw >
org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_except
> ion->getInputStream()); > } > throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception: > $_exception_id"); > } catch(Exception $_exception) { > throw $_exception; > } finally { > $this->_releaseReply($_input); > } > ... > ?> > > Since we don't have finally, the current code is: > > <? > ... > $_input = null; > try { > $_output = $this->_request('bind',true); > org__omg__CosNaming__NameHelper::write($_output,$n); > $_output->write_Object($obj); > $_input = $this->_invoke($_output); > $this->_releaseReply($_input); //PHP still does not have FINALLY
!!!
> return; > } catch(org__omg__CORBA__portable__RemarshalException $_exception) { > $this->_releaseReply($_input); //PHP still does not have FINALLY
!!!
> continue; > } catch(org__omg__CORBA__portable__ApplicationException $_exception) { > $_exception_id = $_exception->getId(); > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { > $this->_releaseReply($_input); //PHP still does not have
FINALLY
> !!! > throw >
org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception-
> >getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { > $this->_releaseReply($_input); //PHP still does not have
FINALLY
> !!! > throw >
org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_excep
> tion->getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { > $this->_releaseReply($_input); //PHP still does not have
FINALLY
> !!! > throw >
org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_excepti
> on->getInputStream()); > } > if ($_exception_id == > org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { > $this->_releaseReply($_input); //PHP still does not have
FINALLY
> !!! > throw >
org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_except
> ion->getInputStream()); > } > $this->_releaseReply($_input); //PHP still does not have FINALLY
!!!
> throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception: > $_exception_id"); > } catch(Exception $_exception) { > $this->_releaseReply($_input); //PHP still does not have FINALLY
!!!
> throw $_exception; > } > $this->_releaseReply($_input); //PHP still does not have FINALLY !!! > ... > ?> > > IMHO, I think that replicating the finally code at the end of every catch > block, before every throw/return statement and at the end of the try/catch > statement justify the need of "finally". > If there is another aproach without "finally" and without code redundancy,
I
> really need it. >
Any ideas ? Best Regards, Cristiano Duarte

Andrew Smith

22 years ago
Cristiano Duarte wrote:
>>Hi internals ! >> >>I came into a problem when writing an IDL to PHP5 language mapping >>specification and an IDL to PHP5 language compiler. I'm using the community >>OpenORB IDL-to-Java compiler as a base for writing the IDL-to-PHP5 compiler, >>in fact, it is a translation from Java to PHP5. Everything is ok except the >>"finally" clause wich doesn't exists in Zend Engine 2. I know that many of >>you think that "finally" is useless but consider this case, and if anyone >>have a simple and elegant solution without implementing "finally" I'll be >>glad to listen.
That's great! An IDL to PHP compiler is really needed ! What's the status of your project anyway ? I'm not shure, but I guess Marcus said that finally is useless in PHP...
>>The code would be like this if we had finally: >><? >> ... >> $_input = null; >> try { >> $_output = $this->_request('bind',true); >> org__omg__CosNaming__NameHelper::write($_output,$n); >> $_output->write_Object($obj); >> $_input = $this->_invoke($_output); >> return; >> } catch(org__omg__CORBA__portable__RemarshalException $_exception) { >> continue; >> } catch(org__omg__CORBA__portable__ApplicationException $_exception) { >> $_exception_id = $_exception->getId(); >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { >> throw org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { >> throw org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { >> throw org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { >> throw org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_exception->getInputStream()); >> } >> throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception:$_exception_id"); >> } catch(Exception $_exception) { >> throw $_exception; >> } finally { >> $this->_releaseReply($_input); >> } >> ... >>?>
Humm...
>> >>Since we don't have finally, the current code is: >> >><? >> ... >> $_input = null; >> try { >> $_output = $this->_request('bind',true); >> org__omg__CosNaming__NameHelper::write($_output,$n); >> $_output->write_Object($obj); >> $_input = $this->_invoke($_output); >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> return; >> } catch(org__omg__CORBA__portable__RemarshalException $_exception) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> continue; >> } catch(org__omg__CORBA__portable__ApplicationException $_exception) { >> $_exception_id = $_exception->getId(); >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__NotFoundHelper::id()) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw org__omg__CosNaming__NamingContextPackage__NotFoundHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::id()) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw org__omg__CosNaming__NamingContextPackage__CannotProceedHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::id()) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw org__omg__CosNaming__NamingContextPackage__InvalidNameHelper::read($_exception->getInputStream()); >> } >> if ($_exception_id == org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::id()) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw org__omg__CosNaming__NamingContextPackage__AlreadyBoundHelper::read($_exception->getInputStream()); >> } >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw new org__omg__CORBA__UNKNOWN("Unexpected User Exception:$_exception_id"); >> } catch(Exception $_exception) { >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> throw $_exception; >> } >> $this->_releaseReply($_input); //PHP still does not have FINALLY !!! >> ... >>?> >> >>IMHO, I think that replicating the finally code at the end of every catch >>block, before every throw/return statement and at the end of the try/catch >>statement justify the need of "finally".
Agreed. You pointed out an example that really needs finally.
>>If there is another aproach without "finally" and without code redundancy, I really need it.
I can't think of another solution right now. But if I figure out something I'll let you know. Best Regards, Andrew Smith, Dr.

Cristiano Duarte

22 years ago
Hi Andrew,
> That's great! An IDL to PHP compiler is really needed ! > What's the status of your project anyway ?
Currently I have the mapping specification done, but it needs validation with the code generated by the compiler. The compiler generates the PHP code, and a simple test works with a Java CORBA server and a PHP CORBA client. At the moment, the extension suports some basic types, TypeCode and Interface.
> I'm not shure, but I guess Marcus said that finally is useless in PHP...
I know. That's why I put some piece of code here. Maybe I can change his mind... :-)
> Agreed. You pointed out an example that really needs finally.
Thanx
> I can't think of another solution right now. But if I figure out > something I'll let you know.
Ok. Best Regards, Cristiano Duarte

Cristiano Duarte

22 years ago
Hi internals ! I really need an opinion about this. Cristiano Duarte

Andi Gutmans

22 years ago
I've stated my opinion in the past (search the archives) and I don't think it'd be feasible (nor critical) to implement this... Andi At 07:15 PM 10/30/2003 -0200, Cristiano Duarte wrote:

Cristiano Duarte

22 years ago
Hi Andi,
> I've stated my opinion in the past (search the archives) and I don't think > it'd be feasible (nor critical) to implement this...
Do you agree that if we don't have finally we should have a way to catch all exceptions ? Let me explain: If you have a library that can raise a huge number of different exceptions and you don't have finally, you should treat all exceptions at the same try/catch block, and rethrow the exceptions that should propagate. If you have finally, you can treat just the exceptions you need and leave the others to be treated by the caller. For example: if you don't have finally, don't have a "catch-all" clause and lock some resouce inside a try block, you need to unlock it: 1) in the try block: before every return statement after the resource allocation 2) write a catch block for all possible exceptions that could be raised and put the code before every return/throw statement (this could be dozens of times) 3) at the end of the try/catch block If you have finally, you just put the same code inside the finally block. No need to catch every exceptions one-by-one, no need to rethrow exceptions that shouldn't be caught, no need to make code redundancy... I know it's not critical, but IMHO it's important. I hope I was clear enough... :-) Cristiano Duarte

Cristiano Duarte

22 years ago
Hi Andi,
> I've stated my opinion in the past (search the archives) and I don't think > it'd be feasible (nor critical) to implement this...
Do you agree that if we don't have finally we should have a way to catch all exceptions ? Let me explain: If you have a library that can raise a huge number of different exceptions and you don't have finally, you should treat all exceptions at the same try/catch block, and rethrow the exceptions that should propagate. If you have finally, you can treat just the exceptions you need and leave the others to be treated by the caller. For example: if you don't have finally, don't have a "catch-all" clause and lock some resouce inside a try block, you need to unlock it: 1) in the try block: before every return statement after the resource allocation 2) write a catch block for all possible exceptions that could be raised and put the code before every return/throw statement (this could be dozens of times) 3) at the end of the try/catch block If you have finally, you just put the same code inside the finally block. No need to catch every exceptions one-by-one, no need to rethrow exceptions that shouldn't be caught, no need to make code redundancy... I know it's not critical, but IMHO it's important. I hope I was clear enough... :-) Cristiano Duarte

Marcus Börger

22 years ago
Hello Cristiano, Friday, November 7, 2003, 4:15:06 PM, you wrote:
> Hi Andi, >> I've stated my opinion in the past (search the archives) and I don't think >> it'd be feasible (nor critical) to implement this...
> Do you agree that if we don't have finally we should have a way to catch all exceptions ?
> Let me explain: > If you have a library that can raise a huge number of different > exceptions and you don't have finally, you should treat all exceptions at > the same try/catch block, and rethrow the exceptions that should propagate. > If you have finally, you can treat just the exceptions you need and > leave the others to be treated by the caller.
> For example: if you don't have finally, don't have a "catch-all" clause > and lock some resouce inside a try block, you need to unlock it: > 1) in the try block: before every return statement after the resource allocation > 2) write a catch block for all possible exceptions that could be > raised and put the code before every return/throw statement (this could be > dozens of times) > 3) at the end of the try/catch block
> If you have finally, you just put the same code inside the finally > block. No need to catch every exceptions one-by-one, no need to rethrow > exceptions that shouldn't be caught, no need to make code redundancy...
> I know it's not critical, but IMHO it's important. I hope I was clear enough... :-)
Regarding catch all the current idea of most developers i spoke to on the conf was that every exception should inherit from the buildin class exception. And therefor a simple catch(Exception $e) would do the trick.
-- Best regards, Marcus mailto:helly@php.net

Sebastian Bergmann

22 years ago
Cristiano Duarte wrote:
> Since we don't have finally, the current code is:
In PHPUnit I use the following code public function runBare() { $catchedException = null; $this->setUp(); try { $this->runTest(); } catch (Exception $e) { $catchedException = $e; } $this->tearDown(); // Workaround for missing "finally". if ($catchedException !== null) { throw $catchedException; } } Works fine for me [tm].
-- Sebastian Bergmann http://sebastian-bergmann.de/ http://phpOpenTracker.de/ Das Buch zu PHP 5: http://professionelle-softwareentwicklung-mit-php5.de/