NYCPHP Meetup

NYPHP.org

[nycphp-talk] PHP 5 Throwing Exceptions in Constructors

Hans Zaunere lists at zaunere.com
Wed Feb 9 17:15:00 EST 2005


> > All PHP 5 code examples I've seen show try/catch pairs like this:
> >
> > try {
> > 	$obj = new MyClass;
> > 	$obj->DoSomething();
> > } catch( Exception $e ) {
> > 	echo $e->getMessage();
> > }
> >
> 
> This is correct.
> 
> > I am the only one in thinking that these examples are incorrect 99%
> > of the time?  Based on other languages, like Java, exceptions should
> > very very rarely be thrown from a class' constructor.  The simple
> > reason, as in PHP 5, is that the object never gets created if an
> > exception is thrown in the constructor.
> 
> PHP is not Java. :)

Riiiight... but it does have the same behavior :)

> > Is there something particular to PHP 5 that I'm missing?  While it
> > could be considered pedantic, PHP 5 code examples should be as:
> 
> > $obj = new MyClass;
> >
> > try {
> > 	$obj->DoSomething();
> > } catch( Exception $e ) {
> > 	echo $e->getMessage();
> > }
> >
> 
> This is incorrect.
> 
> > In fact, in PHP 5 I cannot find anyway to determine the "return"
> > value of the new operator.  This leads me to believe that PHP 5's
> > concept of proper OO is to always assume the object is created
> > successfully, unless a catastrophic event happens, in which case an
> > exception is thrown, and the object isn't created at all.  This of
> > course makes sense, but then I'm confused as to why the code samples
> > all seem a bit incorrect.
> 
> In PHP 5, the way to signal failure in a constructor is to throw an
> exception. There is no other way to communicate errors. As "new" will
> not return "false".
> 
> Exceptions do not have to occur due to catastrophic failures, such as
> lack of memory. This can also occur due to bad input parameters. For
> example, passing the wrong number of parameters, or if you try to
> create a DOMElement with an illegal XML element name.

But what if a class should still be instantiated, even if some of the arguments are incorrect, or subsequent parts fail for some reason?  True, this validation could be done outside of the constructor, even in a totally different class that the constructor instantiates itself, but this still would prevent the instantiation of the original class.

class Top
{
	protected $Child;

	public function __construct( $value ) {
		$this->Child = new Child($value);
	}
}

class Child
{
	public function __construct( $value ) {
		throw new Exception('Bad Value');
	}
}

try {
	$mytop = new Top($_POST);
} catch( Exception $e ) {
	echo 'You had an exception';
}


In the case above, it'd obviously be trivial to change, but with complex class relationships, and factory methods as my particular case involves, it gets cumbersome.  Thus, it seems that instantiation of a class that might have some parts of it not successfully work out, which could be totally acceptable, would cause the Top class to not be created at all, and force the $mytop = new Top($_POST); to be done outside the try/catch, with subsequent checks done inside a try/catch.


---
Hans Zaunere
President, Founder
New York PHP
http://www.nyphp.org





More information about the talk mailing list