:) .. this is almost exactly what I suggested to Bill last week for exactly the same reasons (see the API: http://www.php.net/exceptions ). To see the problem in detail, please consider the attached scripts and their output.

Due to the time pressure of the 0.6 release, and the likely time required for consensus regarding resolution of this issue, I resorted to using __CLASS__ . __FUNCTION__ . __LINE__ in the message thrown by some changes in changeset 2387. However, I'm not exactly fond of this either, and welcome suggestions (like Ralph's) for obtaining similar functionality with less code bloat.

I agree with John that we can likely extend Zend_Exception and add another workaround by adding methods to Zend_Exception, but I have reservations about adding more code to ZF to solve problems caused by a performance optimization in Zend.php that was added to address a perceived problem with PHP's performance when loading numerous files containing only one line of code, such as:

          class Zend_Component_Exception extends Zend_Exception {}

Various Alternatives (in no particular order)
====================================
Aggregate all these "one liners" into a single file, and dispense with attempts to optimize the loading of these one liners.

For "empty" exception classes, use a shared class, combined with a user-defined exception code ( http://www.php.net/exceptions ).

Ignore the perceived performance issue (might not be present / severe when using various byte-code caching tools under real-world conditions), and return to the original approach for handling exceptions in the ZF.

There are several other possibilities, but do any provide the same functionality without resorting to numerous files containing an empty class definition?

Cheers,
Gavin

Ralph Schindler wrote:
Yes, this is the case, the exception object will populate its internal members at construction time, and having been thrown makes no alterations to internal members. This is good b/c a trace at the time of construction will persist until/or when the developer wishes to handle it.

I personally don't need line/file as much as exception type, so this has little affect on me. But to appease those that rely on file/line, why not add to methods to the Zend_Exception class (which extends exception and it is expected that all core exception classes derive from.

class Zend_Exception extends Exception
{
    ...
    final function getTraceLine($traceDepth = 1) { ... }
    final function getTraceFile($traceDepth = 1) { ... }
}

This will allow developers to lines and files from the trace, not the constructor. Bam, everyone happy ;)

-ralph


Bill Karwin wrote:
Okay I just tried this:

<?php
function testException()
{
   require_once 'Zend.php';
   try {
       $x = Zend::exception('Zend_Exception', 'boo!');
       throw $x;
   } catch (Zend_Exception $e) {
       echo "{$e->getMessage()}\n";
       echo "file: {$e->getFile()}\n";
       echo "line: {$e->getLine()}\n";
       echo "trace: {$e->getTraceAsString()}\n";
   }
}

testException();
?>
<?php

error_reporting( E_ALL | E_STRICT );

require 'Zend.php';

class Foo
{
    public function doit()
    {
        //echo "\n", __FILE__, __FUNCTION__, __LINE__, "\n";
        throw new Foo_Exception('message of thrown exception)');
        //throw Zend::exception('Foo_Exception', 'message of thrown exception');
    }
}

class Foo_Exception extends Exception
{}


try {
    $foo = new Foo();
    $foo->doit();
} catch (Exception $e) {
    echo "\nprint_r(\$e)=\n";
    print_r($e);
    echo "\nvar_dump(\$e)=\n";
    var_dump($e);
}
print_r($e)=
Foo_Exception Object
(
    [message:protected] => message of thrown exception)
    [string:private] => 
    [code:protected] => 0
    [file:protected] => 
/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e1.php
    [line:protected] => 12
    [trace:private] => Array
        (
            [0] => Array
                (
                    [file] => 
/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e1.php
                    [line] => 23
                    [function] => doit
                    [class] => Foo
                    [type] => ->
                    [args] => Array
                        (
                        )

                )

        )

)

var_dump($e)=
object(Foo_Exception)#2 (6) {
  ["message:protected"]=>
  string(28) "message of thrown exception)"
  ["string:private"]=>
  string(0) ""
  ["code:protected"]=>
  int(0)
  ["file:protected"]=>
  string(63) "/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e1.php"
  ["line:protected"]=>
  int(12)
  ["trace:private"]=>
  array(1) {
    [0]=>
    array(6) {
      ["file"]=>
      string(63) 
"/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e1.php"
      ["line"]=>
      int(23)
      ["function"]=>
      string(4) "doit"
      ["class"]=>
      string(3) "Foo"
      ["type"]=>
      string(2) "->"
      ["args"]=>
      array(0) {
      }
    }
  }
}
<?php

error_reporting( E_ALL | E_STRICT );

require 'Zend.php';

class Foo
{
    public function doit()
    {
        //echo "\n", __FILE__, __FUNCTION__, __LINE__, "\n";
        //throw new Foo_Exception('message of thrown exception)');
        throw Zend::exception('Foo_Exception', 'message of thrown exception');
    }
}

class Foo_Exception extends Exception
{}


try {
    $foo = new Foo();
    $foo->doit();
} catch (Exception $e) {
    echo "\nprint_r(\$e)=\n";
    print_r($e);
    echo "\nvar_dump(\$e)=\n";
    var_dump($e);
}
print_r($e)=
Foo_Exception Object
(
    [message:protected] => message of thrown exception
    [string:private] => 
    [code:protected] => 0
    [file:protected] => /cygdrive/c/gavin/home/src/zftrunk/library/Zend.php
    [line:protected] => 229
    [trace:private] => Array
        (
            [0] => Array
                (
                    [file] => 
/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e2.php
                    [line] => 13
                    [function] => exception
                    [class] => Zend
                    [type] => ::
                    [args] => Array
                        (
                            [0] => Foo_Exception
                            [1] => message of thrown exception
                        )

                )

            [1] => Array
                (
                    [file] => 
/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e2.php
                    [line] => 23
                    [function] => doit
                    [class] => Foo
                    [type] => ->
                    [args] => Array
                        (
                        )

                )

        )

)

var_dump($e)=
object(Foo_Exception)#2 (6) {
  ["message:protected"]=>
  string(27) "message of thrown exception"
  ["string:private"]=>
  string(0) ""
  ["code:protected"]=>
  int(0)
  ["file:protected"]=>
  string(51) "/cygdrive/c/gavin/home/src/zftrunk/library/Zend.php"
  ["line:protected"]=>
  int(229)
  ["trace:private"]=>
  array(2) {
    [0]=>
    array(6) {
      ["file"]=>
      string(63) 
"/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e2.php"
      ["line"]=>
      int(13)
      ["function"]=>
      string(9) "exception"
      ["class"]=>
      string(4) "Zend"
      ["type"]=>
      string(2) "::"
      ["args"]=>
      array(2) {
        [0]=>
        string(13) "Foo_Exception"
        [1]=>
        string(27) "message of thrown exception"
      }
    }
    [1]=>
    array(6) {
      ["file"]=>
      string(63) 
"/cygdrive/c/gavin/home/src/zftrunk/incubator/jexceptions/e2.php"
      ["line"]=>
      int(23)
      ["function"]=>
      string(4) "doit"
      ["class"]=>
      string(3) "Foo"
      ["type"]=>
      string(2) "->"
      ["args"]=>
      array(0) {
      }
    }
  }
}

Reply via email to