Page 1 of 1
Error handling in my database class: Perhaps an Observer?
Posted: Thu Aug 31, 2006 2:35 pm
by Oren
I'm currently working on my database class. My constructor takes 4 arguments ($db_host, $db_username, $db_password, $db_name). I want it so when one or more arguments are missing an exception will be thrown and the missing arguments will be printed out.
For example, when $db_password and $db_name will be missing, an error like this will be printed:
Some information is missing (db_password, db_name)
Here is how I did it at first - this is the beginning of my constructor:
Code: Select all
public function __construct($db_host = null, $db_username = null, $db_password = null, $db_name = null)
{
/* First, we make sure that all the required settings exist */
/* Create an array from the arguments supplied to the constructor */
$db_info_array = compact('db_host', 'db_username', 'db_password', 'db_name');
/* Now we filter all the elements which are NOT null - so we are left with an array
which holds only the missing arguments */
$db_info_array = array_filter($db_info_array, 'is_null');
/* If one or more arguments were missing, the next 'if' will execute */
if (count($db_info_array) !== 0)
{
/* Create an array from the keys of '$db_info_array' */
$missing_info = array_keys($db_info_array);
/* Converting it to a list of the missing settings separated by commas */
$missing_info = implode(', ', $missing_info);
/* Security... */
unset($db_host, $db_username, $db_password, $db_name, $db_info_array);
throw new exception('Some information is missing (' . $missing_info . ')');
}
/* If we reached here, all the required settings were found and therefore we try
to establish a connection */
//...
}
But the I thought to myself: "Damn, all this error handling is over the scope of this class".
So I thought about replacing the current error handling part (as in the above code) with this:
Code: Select all
public function __construct($db_host = null, $db_username = null, $db_password = null, $db_name = null)
{
if (func_num_args() !== 4)
{
// Don't know what to put here yet
}
//...
}
Now what should I put there? I'm new to design patterns, is this an Observer scenario? (thanks
d11wtq 
)
Posted: Thu Aug 31, 2006 2:49 pm
by Chris Corbyn
The only way to get an observer working inside the constructor would be to pass the observer as an argument to the constructor, rather than loading it later.
Using an observer for error handling does provide flexibility though. Your classes only needs to know an error was generated, it need not worry what the practical implication of the error is.
You'd just trigger the error like:
Code: Select all
if (func_num_args() !== 4)
{
$this->errorMsg('4 arguments were expected but not seen');
}
And the errorMsg() method might just look like:
Code: Select all
function errorMsg($error)
{
foreach ($this->observers as $o)
{
$o->setError($error);
}
}
If the above is PHP4 code you'd want to make sure you're working on the original objects and not a copy, thus using the keys from the loop to access the objects at their original location from the observers container.
Posted: Thu Aug 31, 2006 2:52 pm
by Weirdan
what about this?
Code: Select all
if (func_num_args() !== 4) {
throw new exception('Required argument is missing, expected (db_host, db_username,db_password, db_name)');
}
Or just leave out the default values and let the php do the job for you.
Posted: Thu Aug 31, 2006 3:16 pm
by Oren
d11wtq wrote:You'd just trigger the error like:
I know how to do it (I've read your article

), that's not the question. The question was: An Observer is the right solution here?
d11wtq wrote:If the above is PHP4 code
Does it look like PHP 4? Don't you see the __construct()?
Weirdan wrote:what about this?
Code: Select all
if (func_num_args() !== 4) {
throw new exception('Required argument is missing, expected (db_host, db_username,db_password, db_name)');
}
I guess you are right, this would be the fastest solution since it does not check which argumets were missing. Now, when I think about it more, printing out the missing arguments will not help that much anyway.
Thanks guys

Posted: Sat Sep 02, 2006 4:32 am
by BDKR
d11wtq wrote:
Code: Select all
function errorMsg($error)
{
foreach ($this->observers as $o)
{
$o->setError($error);
}
}
Hmmmm.......???? So then all observers have a setError() method? Or is setError() just a "setter" and the actual processing or display of the error is handled by a different method or object?
Observers are certianly cool but this doesn't seem right. What's wrong with some good old message passing to an error object that the db class is aware of? The db can hold a referrence to it as a member variable then just do ...
Code: Select all
$this->errorObject->processError('Something blew up holmes!');
Perhaps the constructor could look like ...
Code: Select all
function dbClass($arg1, $arg2, $arg3, &$error)
{
/* Do something with the $args */
$this->errorObject=$error;
/* Do something constructive */
}
I hope none of that sounds like it's way out in space.
Cheers,
BDKR
Posted: Sat Sep 02, 2006 4:44 am
by Oren
BDKR wrote:Hmmmm.......???? So then all observers have a setError() method? Or is setError() just a "setter" and the actual processing or display of the error is handled by a different method or object?
Yes, all Observers have a setError() method.
For more information about the Observer read this:
http://phpbook.quantum-star.com/doku.ph ... e_observer
Posted: Sat Sep 02, 2006 5:06 am
by Yossarian
What kind of stymies me is that I want to make sure the calling script can detect the error and "degrade gracefully" with a nice helpful message.
I mean in an mvc environment, does your Observer force a View to appear with a nice helpful message?
I am fairly new to patterns myself.
It isnt a dbconn class, but does something similar - which includes dbconn
I decided to create 2 attributes $msg and $err. $err would be given things like missing args messages.
This was the only way I could figure out how to unit test it too -
assertPattern('/missing/',$this->err);
If $err contains anything the calling script knows to stop.
Code: Select all
$conn= new conn;
....
if($conn->err){
//load a view containing that error message
}else{
//get on with it
}
However - like the original poster says - it feels my dbconn class is doing too much.
Posted: Sat Sep 02, 2006 9:15 am
by feyd
Oren wrote:BDKR wrote:Hmmmm.......???? So then all observers have a setError() method? Or is setError() just a "setter" and the actual processing or display of the error is handled by a different method or object?
Yes, all Observers have a setError() method.
For more information about the Observer read this:
http://phpbook.quantum-star.com/doku.ph ... e_observer
Since when has all Observers had a setError() method? Last I checked, the "standard" Observer needed only one method: Update(). The Observable would have three methods: Attach(), Detach(), and Notify().
Posted: Sat Sep 02, 2006 9:28 am
by Chris Corbyn
In my example I just indicate that the observer contains a method the observable is aware of of. Not all observers have a setError() method, that would be silly. But in my example, the observers which get loaded do. Common practice is to name methods notify() in both the observer and the observable, but it's not so descriptive and needn't use those names if the observers loaded need only deal with a certain task.
Attach, detach, aka loadObserver() and removeObserver() (if you provided keys to do so). I don't think the names matter... it's just the concept of passing messages between loosely coupled objects that needs to be understood.
Posted: Sat Sep 02, 2006 10:16 am
by Oren
feyd wrote:Since when has all Observers had a setError() method? Last I checked, the "standard" Observer needed only one method: Update(). The Observable would have three methods: Attach(), Detach(), and Notify().
d11wtq wrote:In my example I just indicate that the observer contains a method the observable is aware of of.
Posted: Sat Sep 02, 2006 10:40 am
by BDKR
d11wtq wrote:
In my example I just indicate that the observer contains a method the observable is aware of of. Not all observers have a setError() method, that would be silly. But in my example, the observers which get loaded do. Common practice is to name methods notify() in both the observer and the observable, but it's not so descriptive and needn't use those names if the observers loaded need only deal with a certain task.
Attach, detach, aka loadObserver() and removeObserver() (if you provided keys to do so). I don't think the names matter... it's just the concept of passing messages between loosely coupled objects that needs to be understood.
Ahhh....., I see now. Ultimately, my response was guided by my practice.
Do I like this observer stuff? Not really, but once again, this is because of practice. However, the bit about ...
d11wtq wrote:
...passing messages between loosely coupled objects...
... is a key point here. In a library that I work with, it
can't be said that the error object is loosely coupled.
However.....
d11wtq wrote:
In my example I just indicate that the observer contains a method the observable is aware of.
If this is the case, couldn't the mechanism used for notifying this particular observer be simplified and direct instead of looping through the array of
all of the observers and notifiying all of them?
Now having just asked that question, I can still see usage for Observers in a project as long as their scope isn't too broad. As stated, it
really can help get loosely coupled objects to pass messages amongst one another without either having to know the others interface.
Cheers,
BDKR
Re: Error handling in my database class: Perhaps an Observer
Posted: Sat Sep 02, 2006 11:32 am
by Christopher
If the parameters are required and you want to throw an exception then I would just do:
Code: Select all
public function __construct($db_host, $db_username, $db_password, $db_name)
{
if (! ($db_host && $db_username && $db_password && $db_name)) {
throw new exception("Some information is missing ($db_host, $db_username, password, $db_name)");
}
}
Or if you want to handle errors with by checking an isError() method, which I prefer, then:
Code: Select all
public function __construct($db_host, $db_username, $db_password, $db_name)
{
if (! ($db_host && $db_username && $db_password && $db_name)) {
$this->errMsg = "Some information is missing ($db_host, $db_username, password, $db_name)";
}
}
Posted: Sat Sep 02, 2006 11:55 am
by Chris Corbyn
~BDKR, I think observers only really start to become noticably useful when you have more than one respoding to messages at the same time. I can see how just using the one may seem pointless when you can just use tight coupling on the assumption that errors will always be given to a particular interface.
Posted: Sat Sep 02, 2006 12:10 pm
by BDKR
d11wtq wrote:~BDKR, I think observers only really start to become noticably useful when you have more than one respoding to messages at the same time. I can see how just using the one may seem pointless when you can just use tight coupling on the assumption that errors will always be given to a particular interface.
100% agreed!! I was trying to get across that I can see how using Observers makes sense (in spite of my meandering) depending on the needs at hand. I just happened to be continuously developing my own lib of sorts so there is a good deal of close coupling involved. This is the point of view i'm speaking from.
Anyway, I see your point.

Posted: Sat Sep 02, 2006 2:05 pm
by matthijs
BDKR, I think observers only really start to become noticably useful when you have more than one respoding to messages at the same time
That's why your example on the book site is pretty cool. For a login class it's quite realistic that at some point you not only want to throw an error but also want to log the errors (failed login attempts f.e.) in some way.
I can imagine that in the regular app you don't have to be notified of each failed attempt to connect to the db, isn't it? Or maybe you would...