Search code examples
phpoopconstructorclone

php typecast constructor


I would like to typecast PHP exceptions. Consider the following code:

class myException extends Exception {
  function __construct( $mOrigin = "", $iCode = 0, Exception $oPrevious = null){
    if(is_string($mOrigin)){
      parent::__construct($mOrigin, $iCode, $oPrevious);
    } elseif ($mOrigin instanceof Exception) {
      parent::__construct($mOrigin->getMessage(),$mOrigin->getCode(),$mOrigin->getPrevious());
      $this->file = $mOrigin->getFile();
      $this->line = $mOrigin->getLine();
    } else {
      parent::__construct("\$mOrigin has wrong type", self::eFatal, $oPrevious);
    }
  }

The idea is to turn a standard Exception into a myException preserving the original stack trace. Since the variables holding the trace are private I cannot copy these values immediately and the CTOR produces a new one for myException.

The first idea was of course to use clone, but I can hardly re-assign $this, can I?

So what I'm trying to do is a C++ style typecast CTOR. Is there a sensible paradigm in PHP to do this?


Solution

  • Why not just set trace & previous the same way as file & line?

    class myException extends Exception {
      function __construct( $mOrigin = "", $iCode = 0, Exception $oPrevious = null){
        if(is_string($mOrigin)){
          parent::__construct($mOrigin, $iCode, $oPrevious);
        } elseif ($mOrigin instanceof Exception) {
          parent::__construct($mOrigin->getMessage(),$mOrigin->getCode(),$mOrigin->getPrevious());
          $this->file     = $mOrigin->getFile();
          $this->line     = $mOrigin->getLine();
          $this->trace    = $mOrigin->getTrace();
          $this->previous = $mOrigin->getPrevious();
        } else {
          parent::__construct("\$mOrigin has wrong type", self::eFatal, $oPrevious);
        }
      }
    

    EDIT:

    See comments below regarding why I got away w/ this code earlier.

    Why not turn your myException class into a decorator:

    class myException extends Exception {
      private $_oException;
    
      function __construct( $mOrigin = "", $iCode = 0, Exception $oPrevious = null){
        if(is_string($mOrigin)){
          parent::__construct($mOrigin, $iCode, $oPrevious);
        } elseif ($mOrigin instanceof Exception) {
          $this->_oException = $mOrigin;
          parent::__construct($mOrigin->getMessage(),$mOrigin->getCode(),$mOrigin->getPrevious());
          $this->file     = $mOrigin->getFile();
          $this->line     = $mOrigin->getLine();
        } else {
          parent::__construct("\$mOrigin has wrong type", self::eFatal, $oPrevious);
        }
      }
    
      function getTrace()
      {
         return $this->_oException->getTrace();
      }
    
      function getPrevious()
      {
        return $this->_oException->getPrevious();
      }
    }
    

    FUTHER INFO:

    I've followed up on php-general and it turns out this is the intended behavior and it works the same in Java et al as well. You can override the member variable in child classes and have a separate store with the same name. This compiles just fine in java

    public class PrivateAccess
    {
        private Boolean isAccessible = true;
    
        public Boolean getAccessible()
        {
            return isAccessible;
        }
    }
    class PrivateAccessChild extends PrivateAccess
    {
        private Boolean isAccessible = false;
    
        public Boolean getAccessible()
        {
            return isAccessible;
        }
    
        public Boolean getParentAccessible()
        {
            return super.getAccessible();
        }
    
        public static void main(String[] args)
        {   
            PrivateAccessChild pAccess = new PrivateAccessChild();
    
            if(!pAccess.getAccessible())
                System.out.println("we're hitting the child here...");
    
            if(pAccess.getParentAccessible())
                System.out.println("we're hitting the parent here...");
    
            System.out.println("we're done here...");
        }
    }