469,282 Members | 2,000 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

How to pass Additional Parameters to register_shutdown_function()

code green
1,726 Expert 1GB
The PHP manual rather helpfully states
It is possible to pass parameters to the shutdown function by passing additional parameters.
sic. But gives no example.
How exactly does this work. I use shutdown function to wrap up errors from various classes something like this.
Expand|Select|Wrap|Line Numbers
  1. function shutdownFunc()
  2. {                        
  3.     global $errorobj;
  4.     global $mydb;
  5.     if(is_object($mydb)) {disconnectDB($mydb,$errorobj)};
  6. }
But rather than using global, how would class objects be passed as a parameter?
I could guess, but maybe somebody already knows the answer.
Thanks
Feb 22 '11 #1
13 5381
Dormilich
8,651 Expert Mod 8TB
listed in the manual:
void register_shutdown_function ( callback $function [, mixed $parameter [, mixed $... ]] )
if you have a mysql class, use the class’s destructor.

PS. PHP’s database abstraction layer PDO closes the connection by default.
Feb 23 '11 #2
code green
1,726 Expert 1GB
Thanks Dormilich, but as register_shutdown_function() is generally called early in scripts,
most of my class objects have not yet been instantiated, so they cannot be passed as parameters yet.

I have never been successful in using __destructor() to pass error messages to an error class as rightly so, they have no knowledge of each other.
A simplified idea of how I handle errors is...
Each class, and there may be MySQL, MsSQL, CSV, XML as well as an error class, collects and saves errors internally (string or array),
when the script finishes register_shutdown_function() collects all the errors and passes them to a mail/display class to be reported.

I started using register_shutdown_function() like this for debugging and found it extremely useful,
but also found it works wonderfully for live programs.
Am I doing something weird, is there a more recognised way of error handling?
Feb 23 '11 #3
Dormilich
8,651 Expert Mod 8TB
Thanks Dormilich, but as register_shutdown_function() is generally called early in scripts, most of my class objects have not yet been instantiated, so they cannot be passed as parameters yet.
then this is clearly a design error. for PHP it doesnít matter where you define the shutdown handlers, as they will always executed on script end / exit. why not defining it when you actually construct your objects?

I have never been successful in using __destructor() to pass error messages to an error class as rightly so, they have no knowledge of each other.
the method is called __destruct(), not __destructor() Ö

I started using register_shutdown_function() like this for debugging and found it extremely useful,
but also found it works wonderfully for live programs.
Am I doing something weird, is there a more recognised way of error handling?
not sure if this is a "recognised" way, but I have an error logging class (well, 2 classes) that sends an email (in case of errors only) when I call its submit() method. sometimes I call it manually and sometimes I put it in the main classís destructor. however, I donít need parameters for it.
Feb 23 '11 #4
code green
1,726 Expert 1GB
then this is clearly a design error..... why not define it when you actually construct your objects
This would mean either constructing all objects at the same time early in the script even though they may not be used,
or calling register_shutdown_function() later and missing a possible early script exit.
The first seems poor practice and the second not much use.

I use a DB class to return data in an array from which say an XML is created.
If there is no data returned then XML is not instantiated.

__destruct() -- sorry about that

I have an error logging class (well, 2 classes) that sends an email (in case of errors only) when I call its submit() method.
Yes I use a similar error logging class to catch general script errors, but other class errors I store up in the class,
then use shutdown function to collect them and pass them to the error logging class.

I use a method called returnErrors() in every class.
Example from my CSV that is called from my shutdown function
Expand|Select|Wrap|Line Numbers
  1. public function returnErrors()
  2. {    
  3.     if($this->msgcount)
  4.     {
  5.         $msg = '<br><b>Errors From CSVclass</b> '.$this->errmsg.
  6.                 '<br>'.basename($this->filename).
  7.                 '<br><b>End of CSVclass errors</b> ';
  8.         $this->errmsg = '';
  9.         $this->msgcount = 0;
  10.         return $msg;
  11.     }
  12.     return '';
  13. }
This tidily bundles them up ready for despatch by email.
Feb 23 '11 #5
Dormilich
8,651 Expert Mod 8TB
This would mean either constructing all objects at the same time early in the script even though they may not be used, or calling register_shutdown_function() later and missing a possible early script exit.
then donít exit early. Exceptions are not there for nothing. besides, you canít close a database connection that you havenít opened, etc.
Feb 23 '11 #6
code green
1,726 Expert 1GB
then donít exit early
If no data is returned the script will finish tidily but without any further processing such as XML.
That is what I mean by exit early, (sorry again, exit wrong word).

This is my dilemma, if I have instantiated all the objects I MIGHT need it seems wasteful.
But if register_shutdown_function is declared later after instantiating XML, it would not be used so I could not collect DB errors.
So I am using global inside the shutdown function and checking if the object exists, if so get any errors and destroy the object.

I would like to do away with these tests and global, which is why I was wondering how parameters could be passed.
Feb 23 '11 #7
Dormilich
8,651 Expert Mod 8TB
So I am using global inside the shutdown function and checking if the object exists, if so get any errors and destroy the object.
does that mean youíre using only one shutdown function???
Feb 23 '11 #8
code green
1,726 Expert 1GB
One per script or collection of scripts.
This means I have a different version for each project.

I was hoping to create a generic shutdown function residing in a high tier file that is called by all projects.
But my current method of using global objects would mean testing for every possible object created, and keeping the names common throughout.

But if objects could be passed dynamically on register_shutdown_function a much simpler high level function could be created.
It seems the only way this can work is creating all class objects that might be required at the beginning then calling register_shutdown_function.

I was wishfully thinking that register_shutdown_function would work another way.
All objects instantiated at the beginning is not too bad.
At least it looks tidy, even though they may not be used.
Feb 24 '11 #9
Dormilich
8,651 Expert Mod 8TB
the good part about register_shutdown_function() is that you can register as many handlers as you need.

from my experience itís better to collect the errors in one place (a common logger class) instead each class taking care of its errors. otherwise you have a tight coupling between classes and errors.
Feb 24 '11 #10
code green
1,726 Expert 1GB
from my experience it’s better to collect the errors in one place (a common logger class) instead each class taking care of its errors
I agree in principle. This means each time any code calls a class method,
this has to be immediately followed by another call to collect any errors from the class error object,
to pass immediately to the error class.
This does seem to be a fairly standard way to do it, but it does rather bulk out code in the calling script.

This is an example of legacy code left by a colleague who favoured PEAR
Expand|Select|Wrap|Line Numbers
  1. $result = $dbc->executeMultiple($dsqls,$newdata);
  2. if(PEAR::isError($result)) 
  3.        $params = handleError($errstack,$result);
When PEAR changed as it seems to do frequently the script broke and I had to modify it.
Another class called savant was handled the same way and I did find it tiring having the script cluttered with error calls throughout.

I kind of prefer having each class store its own errors, then collect at the end.
Feb 25 '11 #11
Dormilich
8,651 Expert Mod 8TB
therefore I rely on Exceptions, because they don’t change.
Expand|Select|Wrap|Line Numbers
  1. try
  2. {
  3.     // some code that throws an Exception on error
  4. }
  5. catch (Exception $e)
  6. {
  7.     ErrorLog::add($e);
  8. }
Feb 25 '11 #12
code green
1,726 Expert 1GB
To be fair, PHP did not have exceptions when this was written.
I notice your Error Logging calls a static method.
I am curious as to what is done in ::add.

I create an instance of my error class and log the errors in a member variable, which at the end may be echoed out but is usually emailed to me.

Why do you prefer a static method?
Feb 25 '11 #13
Dormilich
8,651 Expert Mod 8TB
Why do you prefer a static method?
because an abstract registry pattern only allows static methods/properties.

Expand|Select|Wrap|Line Numbers
  1.     /**
  2.      * get the data collected in MyException() and create a new
  3.      * ErrorEntry object
  4.      * 
  5.      * @param (mixed) $input       an Exception or debug backtrace
  6.      * @param (string) $class      class name where the Exception was caught
  7.      * @return (bool)              exception saved
  8.      */
  9.     public static function add(
  10.         $input, 
  11.         $catch,
  12.         $level = 0
  13.     ) 
  14.     {
  15.         // save Exception
  16.         if ($input instanceof \Exception)
  17.         {
  18.             self::$Log[] = new ErrorEntry($input, $catch, $level);
  19.             return true;
  20.         }
  21.         // save Backtrace
  22.         if (is_array($input)) // $input = debug_backtrace()
  23.         {
  24.             try
  25.             {
  26.                 $msg    = 'Debug Backtrace';
  27.                 $method = isset($input['function']) ?: __METHOD__;
  28.                 throw new MyException(0, $level, $method, $msg, $input);
  29.             }
  30.             catch (MyException $e)
  31.             {
  32.                 self::$Log[] = new ErrorEntry($e, $catch);
  33.                 return true;
  34.             }
  35.         }
  36.         return false;
  37.     }
  38.  
Feb 25 '11 #14

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

3 posts views Thread by JezB | last post: by
2 posts views Thread by Alex Nitulescu | last post: by
4 posts views Thread by pawel.pabich | last post: by
1 post views Thread by Mayhem05 | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.