How to pass Additional Parameters to register_shutdown_function()

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • code green
    Recognized Expert Top Contributor
    • Mar 2007
    • 1726

    How to pass Additional Parameters to register_shutdown_function()

    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.
    Code:
    function shutdownFunc()
    {						
        global $errorobj;
        global $mydb;
        if(is_object($mydb)) {disconnectDB($mydb,$errorobj)};
    }
    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
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    listed in the manual:
    void register_shutdo wn_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.
    Last edited by Dormilich; Feb 23 '11, 12:10 AM.

    Comment

    • code green
      Recognized Expert Top Contributor
      • Mar 2007
      • 1726

      #3
      Thanks Dormilich, but as register_shutdo wn_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_shutdo wn_function() collects all the errors and passes them to a mail/display class to be reported.

      I started using register_shutdo wn_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?

      Comment

      • Dormilich
        Recognized Expert Expert
        • Aug 2008
        • 8694

        #4
        Thanks Dormilich, but as register_shutdo wn_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_shutdo wn_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.

        Comment

        • code green
          Recognized Expert Top Contributor
          • Mar 2007
          • 1726

          #5
          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_shutdo wn_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
          Code:
          public function returnErrors()
          {	
          	if($this->msgcount)
          	{
                  $msg = '<br><b>Errors From CSVclass</b> '.$this->errmsg.
          				'<br>'.basename($this->filename).
          				'<br><b>End of CSVclass errors</b> ';
          	    $this->errmsg = '';
          	    $this->msgcount = 0;
                  return $msg;
              }
              return '';
          }
          This tidily bundles them up ready for despatch by email.

          Comment

          • Dormilich
            Recognized Expert Expert
            • Aug 2008
            • 8694

            #6
            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_shutdo wn_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.

            Comment

            • code green
              Recognized Expert Top Contributor
              • Mar 2007
              • 1726

              #7
              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_shutdo wn_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.

              Comment

              • Dormilich
                Recognized Expert Expert
                • Aug 2008
                • 8694

                #8
                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???

                Comment

                • code green
                  Recognized Expert Top Contributor
                  • Mar 2007
                  • 1726

                  #9
                  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_shutdo wn_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_shutdo wn_function.

                  I was wishfully thinking that register_shutdo wn_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.

                  Comment

                  • Dormilich
                    Recognized Expert Expert
                    • Aug 2008
                    • 8694

                    #10
                    the good part about register_shutdo wn_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.

                    Comment

                    • code green
                      Recognized Expert Top Contributor
                      • Mar 2007
                      • 1726

                      #11
                      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
                      Code:
                      $result = $dbc->executeMultiple($dsqls,$newdata);
                      if(PEAR::isError($result)) 
                             $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.

                      Comment

                      • Dormilich
                        Recognized Expert Expert
                        • Aug 2008
                        • 8694

                        #12
                        therefore I rely on Exceptions, because they don’t change.
                        Code:
                        try
                        {
                        	// some code that throws an Exception on error
                        }
                        catch (Exception $e)
                        {
                        	ErrorLog::add($e);
                        }

                        Comment

                        • code green
                          Recognized Expert Top Contributor
                          • Mar 2007
                          • 1726

                          #13
                          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?

                          Comment

                          • Dormilich
                            Recognized Expert Expert
                            • Aug 2008
                            • 8694

                            #14
                            Why do you prefer a static method?
                            because an abstract registry pattern only allows static methods/properties.

                            Code:
                                /**
                                 * get the data collected in MyException() and create a new
                                 * ErrorEntry object
                                 * 
                                 * @param (mixed) $input       an Exception or debug backtrace
                                 * @param (string) $class      class name where the Exception was caught
                                 * @return (bool)              exception saved
                                 */
                                public static function add(
                                    $input, 
                                    $catch,
                                    $level = 0
                                ) 
                                {
                                    // save Exception
                                    if ($input instanceof \Exception)
                                    {
                                        self::$Log[] = new ErrorEntry($input, $catch, $level);
                                        return true;
                                    }
                                    // save Backtrace
                                    if (is_array($input)) // $input = debug_backtrace()
                                    {
                                        try
                                        {
                                            $msg    = 'Debug Backtrace';
                                            $method = isset($input['function']) ?: __METHOD__;
                                            throw new MyException(0, $level, $method, $msg, $input);
                                        }
                                        catch (MyException $e)
                                        {
                                            self::$Log[] = new ErrorEntry($e, $catch);
                                            return true;
                                        }
                                    }
                                    return false;
                                }

                            Comment

                            Working...