Skip to end of metadata
Go to start of metadata

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[

Zend Framework: Exception codes in exceptions Component Proposal

Proposed Component Name Exception codes in exceptions
Developer Notes http://framework.zend.com/wiki/display/ZFDEV/Exception codes in exceptions
Proposers Matthew Ratzloff
Thomas Weidner
Alexander Veremyev (Zend Liaison)
Revision 2.0 - October 1, 2007: Revised with community feedback; added Thomas to the list of proposers
2.1 - October 2, 2007: Added translation functionalities
2.2 - October 3, 2007: Added use cases
3.0 - July 20, 2008: Reworked as wished by the devteam (wiki revision: 33)

Table of Contents

1. Overview

Currently, exceptions can only be handled on a per-class basis, or possibly by string comparison against the message.

Instead, we propose that exception codes be used throughout the framework, using a 4-byte hexadecimal format.

This has at least four obvious benefits.

First, it's now possible to distinguish exceptions based on the type of error instead of only by class. This allows users to handle them intelligently.

Second, codes let us do some interesting things with exception handling. Users would now be able to call a method such as:

thereby making exception special-casing easy.

Third, this gives us the ability to translate error messages using Zend_Translate (loaded only when an exception occurs) and using separate translation files (for example, .mo format). Not all developers speak English; those that do generally prefer to see exception messages in their native language.

Finally, users could potentially visit something like http://framework.zend.com/exceptions/0xFFFFFFFF (easily indexable by search engines) to see a more in-depth description of the exception, as well as possible solutions and even user comments. Exceptions that are commonly encountered can be addressed once, on the website, in an easy to access way. Zend_Exception's constructor, which all exceptions extend, can then be easily modified to provide a direct link to this page.

Error codes can be divided in a predetermined way, so that each component has its own hex value and no overlap occurs. The solution that we've agreed upon is that each component is assigned its own unique range for the first half (e.g., Zend_Acl = 0x00020000, Zend_Auth = 0x00030000, Zend_Etc = 0xFFFF0000), for a maximum of 65,536 possible exception ranges. Each component then has 65,536 exceptions it can create and use. For example, Zend_Controller's first type of exception may be 0x00030000, followed by 0x00030001, 0x00030002, and so on.

2. References

None

3. Component Requirements, Constraints, and Acceptance Criteria

None

4. Dependencies on Other Framework Components

Zend_Translate - Thomas Weidner for translated exceptions via getTranslatedMessage()

5. Theory of Operation

Initially, this would require nothing except assignment of hex values to components. As time goes on, the translation system could be implemented, followed by the online system which would use the identical translation files from the framework.

Allocation of exception ranges:

0x0000 is reserved for the UNKNOWN exception, which must be declared in each exception class.

6. Milestones / Tasks

7. Class Index

Zend_Exception

8. Use Cases

Use Case 1: (Class) Throwing an exception
Use Case 2: (Class) Throwing an exception with parameters
Use Case 3: (User) Using the standard exception behavior
Use Case 4: (User) Iterating through different exceptions with a switch block
Use Case 5: (User) Using the exception special-casing methods
Use Case 6: (User) Getting a translated exception message
Use Case 7: (User) Translating an exception message to a fixed, expected locale
Use Case 8: (User) Translating an exception message to one of the auto-locales
Use Case 9: (User) Setting a standard locale for all exception objects

In all cases, exceptions are handled thoughtfully and in a very readable way.

9. Class Skeletons

The new Zend_Exception:

An example exception:

]]></ac:plain-text-body></ac:macro>

]]></ac:plain-text-body></ac:macro>

Labels:
exceptions exceptions Delete
translate translate Delete
zend_exception zend_exception Delete
exception exception Delete
codes codes Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Mar 14, 2007

    <p>One problem which comes with this...</p>

    <p>If a value is integrated in a exception message, there must be a way to get the value/s also not only the internal number of the exception.<br />
    "Your input '$date' can not be parsed" for example...</p>

    <p>We would have to consider if all exceptions of the framework are thrown into one file or one file per class as the original file would come from us.</p>

    <p>We should also think of pro's/con's if we use gettext because not all are common with it. CSV or ARRAY adapters or even TMX/XLIFF are human readable and as fast as gettext.</p>

    <p>And I am also not sure if 3 bytes are enough, but principal the idea is good and I like it.</p>

    <p>Thomas<br />
    I18N Team Leader</p>

    1. Mar 14, 2007

      <blockquote>
      <p>One problem which comes with this...</p>

      <p>If a value is integrated in a exception message, there must be a way to get the value/s also not only the internal number of the exception.<br />
      "Your input '$date' can not be parsed" for example...</p></blockquote>

      <p>That's a good point. We could take care of that by passing in an array of values.</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      throw new Zend_Whatever_Exception("'%s' must be an array", 0x320093, array($value));
      ]]></ac:plain-text-body></ac:macro>

      <blockquote>
      <p>We would have to consider if all exceptions of the framework are thrown into one file or one file per class as the original file would come from us.</p></blockquote>

      <p>I suggested separate files for each component simply because one file could become pretty large. Exceptions will be thrown and caught in the course of normal execution of an application, so there's no reason to load and parse a 200 KB (or whatever) file with every request.</p>

      <p>For the sake of the translators, I think one file for each component is a good goal (<code>Zend_Exception</code> can look at the exception's <code><em>CLASS</em></code> and grab the appropriate translation file.</p>

      <blockquote>
      <p>We should also think of pro's/con's if we use gettext because not all are common with it. CSV or ARRAY adapters or even TMX/XLIFF are human readable and as fast as gettext.</p></blockquote>

      <p>The choice of which format to use was left as an exercise for the reader. <ac:emoticon ac:name="wink" /> Truthfully, I prefer TMX, but as you said, any will do (except maybe CSV). The ultimate idea is that eventually all exceptions are stored in a database, and that translators do their translation work over the web. Then a Subversion post-commit hook will create the exception files dynamically.</p>

      <p>Having said that, I still think it's important to mirror the exceptions in the code itself, for people who are most comfortable looking directly at the code to determine how a component works.</p>

  2. Mar 14, 2007

    <p>What happens when an error in Zend_Translate occurs?</p>

    <p>Is is safe to assume, that in any case I'll get to see the message of the exception?</p>

    <p>Btw. 3-bytes allow up to 16777215 different error messages. We are not building Windows here, Thomas <ac:emoticon ac:name="wink" /></p>

    1. Mar 14, 2007

      <blockquote>
      <p>What happens when an error in Zend_Translate occurs?</p></blockquote>

      <p>It is caught within <code>Zend_Exception</code> and the original (English) error is thrown instead.</p>

      <blockquote>
      <p>We are not building Windows here, Thomas</p></blockquote>

      <p>Although, Vista may have turned out better if we had. <ac:emoticon ac:name="wink" /></p>

      1. Mar 14, 2007

        <p>Just to clarify, when I say "original (English) error" I mean the exception message in the code. That's another reason why it's important to still have messages in the code itself.</p>

    2. Mar 15, 2007

      <blockquote><p>What happens when an error in Zend_Translate occurs?</p></blockquote>

      <p>There can only be one possible error:<br />
      The translation file is not present...<br />
      But sorry... is the exception class file or an other file is missing there is something completly wrong with this ZF installation !</p>

      <p>By translation itself never an exception will be thrown.</p>

      <blockquote><p>Btw. 3-bytes allow up to 16777215 different error messages</p></blockquote>

      <p>That's not correct... Matthew said to have the first byte for the component. Which means a maximum of 255/256 components. This is where I could see a problem because in future we may have more that 255/256 components.</p>

      1. Jul 31, 2007

        <p> Btw. 3-bytes allow up to 16777215 different error messages<br />
        That's not correct... Matthew said to have the first byte for the component. Which means a maximum of 255/256 components. This is where I could see a problem because in future we may have more that 255/256 components.<br />
         I would have to agree with Thomas on this, I think we could easily look at more than 255 components.  I believe that the community will grow and then there will components that are not part of the official release, but could be a part of other projects.</p>

        <p> I do like the idea, however, and I would like to see it implemented.</p>

  3. Mar 16, 2007

    <p>This requirement also exists for status messages returned from methods. For example Zend_Valiate_* has a getMessages() method which returns informative messages when validation fails. </p>

    <p>Personally I think it is even more important to be able to translate messages since its more likely they will be displayed to the end user (ideally exceptions would only be seen by developers). So these need to be translated in the same way exceptions do. </p>

    <p>Perhaps getCodes() as well as getMessages() may suffice in this instance, though I'm not sure how many other ZF modules make use of returning messages to the user.</p>

    <p>Does this usage require a new proposal?</p>

  4. Mar 29, 2007

    <p>I'e got idea that exception codes can be ambeded in the class as  constant e.g.</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    class Zend_Loader

    Unknown macro: { const Exception_FileNotFound = 0; const Exception_IllegalFilenameCharacters = 1;  // rest of code here}

    ;  
    ]]></ac:plain-text-body></ac:macro>
    <p> I think it could help in determining kind of exception for a programmer - error codes are helpfull when programmer want to deal with exception and need more precise information - in combination with code completion. In my opinion it could be very convenient.</p>

    <p> BTW What about common exceptions like those above? Should every component have their own code for? Or maybe those kind of exceptions should be standardized?</p>

  5. Jul 16, 2007

    <p>I was just playing with Zend_Filter_Input which in turn brought me to Zend_Validate classes and seeing the problem that they don't appear to support Zend_Translate, then the mailing list and finally led here.</p>

    <p>Seems to me the framework really isn't properly workable for translation yet, or are there workarounds?</p>

    <p>Anyway, some thoughts/questions:</p>

    <p>1) I want all messages to have a code as this then would let me run stats reports from my logs to answer questions like "how's the stability in my app", regarding frequency of exceptions thrown and their severity. "How's my user interface design performing", regarding frequency of failed form validations. I would find this objective feedback very useful in addition to the distinctly subjective feedback I can hope to get by troubling my app's users to let me know when things aren't going well.</p>

    <p>2) Does this proposal mean to provide message code numbering space for people privately extending Zend components? Also, the numbering range should include a user space for the App itself to use. PHP's own error messaging numbering comes to mind. I can't help thinking of the IPv4 story "yeah four octets, that'll be enough" <ac:emoticon ac:name="laugh" /></p>

    <p>3) Since ZF 1.0 everything has to be backwards compatible doesn't it?</p>

    <p>4) If Zend_Translate must be instantiated. Perhaps it should be a singleton? Then classes like Zend_Validate_* could get it and only if it is in an already configured state make use of it thus helping out point 3) maybe?</p>

  6. Sep 26, 2007

    <p>I do agree with one point here: all exceptions should have some kind of unique identifier code. We should probably come up with a more robust scheme than 1-byte/3-byte scheme mentioned, however. This would facilitate building an online knowledge base relating to framework exceptions (as mentioned above) which would be pretty valuable.</p>

    <p>That said, I can't think of any good reason off the top of my head why any exception message should ever be seen by any end user. If that happens, it's by definition a critical failure in the app. I don't see the value in spending any time and energy on I18N for programmer-only app content. The parts of the app that should be translated are UI elements, including validation error messages (which should not be exceptions, since you're app fully expects those to happen in the normal course of operation).</p>

    <p>To be honest, I believe that all the exception handling in the framework needs to be overhauled. The exception classes themselves should be meaningfull classifications of exception types, such as MissingRequiredException, or NotFoundException (the built-in SPL exceptions are a good start). Simply naming the exception class after the class that throws it is utterly useless... that's why we have the stack traces already in the exceptions.</p>

    1. Sep 27, 2007

      <p>I think we have spoken long enough... it's time to begin work. <ac:emoticon ac:name="smile" /></p>

      <p>I think we can summarize this whole thing to 3 different issues:</p>

      <p>*) Include Exception Codes into each thrown Exception<br />
      *) Change Exceptions to throw meaningfull Named Exceptions instead of Class Exceptions<br />
      *) Add a way to translate the returned Text of a exception</p>

      <p>Exception codes<br />
      ---------------<br />
      I think we all apreciate to have exception codes. We just have to clarify how we seperate the components. In my opinion only one byte for components is not enough because we will have more than 256 components in future.</p>

      <p>Possible solution:<br />
      *) Use two bytes for component recognition.<br />
      *) Or use 8 bits for components and 8 bits for exceptions... so each could be 4096. This seems to be enough.</p>

      <p>Meaningfull names<br />
      -----------------<br />
      Instead of "Zend_Component_Exception" it would be better to have "Zend_Component_MissingValueException"<br />
      Only a "MissingValueException" would not be enough and it would brake the naming scheme of ZF.<br />
      But a "Zend_Component_MissingValueException" would be both... ZF compilant and named.</p>

      <p>I would be willing to create a seperate proposal or to change the existing one here if it's ok for Matthew.</p>

      <p>Translation for Exception Strings<br />
      ---------------------------------<br />
      Some Exceptions still would have to be translated. If you have an "Zend_Validate_TooLongException" for example.<br />
      Now this exception would gives you the message "You string 'abcde' is only allowed to have '3' chars!".<br />
      So instead of only getMessage I would propose to eighter add translating functionality to getMessage()</p>

      <p>f.e. getMessage($locale = null);<br />
      If no locale given english... if given translated.</p>

      <p>or a own additional function getTranslatedMessage($locale = null); or just _($locale = null);<br />
      But this way we need also a possibility to have the included strings in the exceptions...<br />
      'abcde' and '3' are only values and are not translateable...<br />
      But you can already look into Zend_Date_Exception for how this can be solved.</p>

      <p>I would also be willing to include this in the proposal.</p>

      <p>Another way would be to have a own class "Zend_Exception_Translate" or so... which would be able to translate a given exception based on the values and the exceptioncode.<br />
      But this doesn't look like it would be ok for the actual ZF implementation.</p>

      <p>Any suggestions ?</p>

      <p>Matthew.. your opinion ? Extend the proposal ? Work together ?</p>

      1. Sep 27, 2007

        <p>Thomas,</p>

        <p>Do you mean 12 bits for each key or value (for a total of 24 bits or 3 bytes)? That's fine. I just posted the initial suggestion of a 1-byte key and 2-byte value to get people talking.</p>

        <p>A possible Zend_Exception constructor signature (to prepare for translation):</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        /**

        • @var array|null
        • Translation parameters
          */
          protected $_params = null;

        /**

        • Constructor.
        • Additional parameters may be passed in after the code for translation purposes.
        • @param string $message Exception message
        • @param integer $code 3-byte hexadecimal exception code (e.g., 0x000000)
        • @param string Translation parameters
          */
          public function __construct($message = null, $code = 0)
          {
          if (func_num_args() > 2)
          Unknown macro: { $this->_params = array_splice(func_get_args(), 2); }

          }

        /**

        • Returns a translated exception message.
        • @param Zend_Locale $locale Locale
          */
          public function getTranslatedMessage(Zend_Locale $locale = null)
          {
          $message = $this->getMessage();
          // Instantiate Zend_Translate and get translated string using $this->_params
          return $message;
          }
          ]]></ac:plain-text-body></ac:macro>

        <p>Allocation of ranges:</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        0x000001 to 0x000FFF - Reserved for PHP bugs
        0x001000 to 0x001FFF - Reserved for general framework exceptions
        0x002000 to 0x002FFF - Zend_Acl
        0x003000 to 0x003FFF - Zend_Auth
        0x004000 to 0x004FFF - Zend_Cache
        0x005000 to 0x005FFF - Zend_Config
        0x006000 to 0x006FFF - Zend_Console
        0x007000 to 0x007FFF - Zend_Controller
        0x008000 to 0x008FFF - Zend_Date
        0x009000 to 0x009FFF - Zend_Db
        0x00A000 to 0x00AFFF - Zend_Debug
        0x00B000 to 0x00BFFF - Zend_Feed
        0x00C000 to 0x00CFFF - Zend_Filter
        0x00D000 to 0x00DFFF - Zend_Gdata
        0x00E000 to 0x00EFFF - Zend_Http
        0x00F000 to 0x00FFFF - Zend_Json
        0x010000 to 0x010FFF - Zend_Loader
        0x011000 to 0x011FFF - Zend_Locale
        0x012000 to 0x012FFF - Zend_Log
        0x013000 to 0x013FFF - Zend_Mail
        0x014000 to 0x014FFF - Zend_Measure
        0x015000 to 0x015FFF - Zend_Memory
        0x016000 to 0x016FFF - Zend_Mime
        0x017000 to 0x017FFF - Zend_Pdf
        0x018000 to 0x018FFF - Zend_Registry
        0x019000 to 0x019FFF - Zend_Request
        0x01A000 to 0x01AFFF - Zend_Rest
        0x01B000 to 0x01BFFF - Zend_Search
        0x01C000 to 0x01CFFF - Zend_Server
        0x01D000 to 0x01DFFF - Zend_Service
        0x01E000 to 0x01EFFF - Zend_Session
        0x01F000 to 0x01FFFF - Zend_Translate
        0x020000 to 0x020FFF - Zend_Uri
        0x021000 to 0x021FFF - Zend_Validate
        0x022000 to 0x022FFF - Zend_Version
        0x023000 to 0x023FFF - Zend_View
        0x024000 to 0x024FFF - Zend_XmlRpc
        ]]></ac:plain-text-body></ac:macro>

        <p>The PHP range beginning with 0x000001 is on purpose, since the default value of $code is 0 (0x000000).</p>

        <p>We can work together, although I think the majority of the work must be done by the component maintainers themselves once we outline the specification.</p>

  7. Sep 27, 2007

    <p>Matthew,</p>

    <p>The 12 bit exception codes are exactly what I meant... I think we can leave it as you defined it.<br />
    Just one small neg... new classes will be added after Zend_XmlRpc and therefor brake the alphabetic order.<br />
    But I think we can live with that <ac:emoticon ac:name="smile" /></p>

    <p>The signature or getTranslatedMessage looks ok for me... </p>

    <p>The work itself:<br />
    I think if we implement the new standard for our classes (MVC and I18N core are the biggest) and have it also integrated by other components which are owned by active members we should have it ready in 2-4 weeks.<br />
    The components which actually have no explicit owner like Zend_Mime or Zend_Uri would have to be done by us.</p>

    <p>The definition of the translation source itself would initially be done by me.<br />
    We will have to create a way where the source can be translated by our docu-members.</p>

    <p>And we have to define which translation adapter to use.<br />
    From the point of speed the gettext adapter would be the best choice.<br />
    From the point of maintenance would be array, csv or the new ini adapter a good choice.<br />
    I would propose for gettext useage but it's not human readable... only with poEdit for example.</p>

    <p>PS: You forgot Zend_Currency which is already in core.</p>

    1. Sep 28, 2007

      <p>I have retought a little bit the proposed "speaking" exception naming scheme.<br />
      I think it's not good from the point of useability... we would have to create xxx classes, one for each exception.</p>

      <p>But beside the "speaking" names for exception we had another idea.</p>

      <p>What about integrating exception constants like this:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      class Zend_Validate_Exception extends Zend_Exception
      {
      const StringTooLong = 0x021010;
      const StringTooShort = 0x021011;
      ...
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>This would also increase readability and we could do somethink like this:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      if ($e->getCode() === Zend_Validate_Exception::StringTooLong) {
      ...
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>This way anyone would not look and know the exception codes.<br />
      This makes the code much more readable.<br />
      ( Thanx crunch for the idea <ac:emoticon ac:name="smile" /> )</p>

      <p>I think that "named" Exceptions would decrease readability along with the actual naming scheme of ZF.</p>

      <p>What we could also do is something like this:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      class Zend_Validate_Exception extends Zend_Exception
      {
      const StringTooLong = 0x021010;
      const StringTooShort = 0x021011;
      ...
      public StringTooLongException()

      Unknown macro: { .... }

      }
      ]]></ac:plain-text-body></ac:macro>

      <p>to have this thrown:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      try {
      ...
      } catch (Zend_Validate_Exception $e)
      if ($e->StringTooLongException())

      Unknown macro: { ... }

      }
      ]]></ac:plain-text-body></ac:macro>

      <p>Just some ideas to be discussed <ac:emoticon ac:name="smile" /></p>

      1. Sep 28, 2007

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[try

        Unknown macro: { ...} catch (Zend_Validate_Exception $e) if ($e->StringTooLongException()){ ... }

        }]]></ac:plain-text-body></ac:macro>
        <p>This seems useful, but in my oppinion there should something to catch illegal calls, eg if somebody is trying to call StringToLongException() on a Zend_View_Exception-object. How about to use __call instead?</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[class Zend_Validate_Exception extends Zend_Exception
        {
        const StringTooLong = 0x021010;
        const StringTooShort = 0x021011;
        ...
        public __call ($name, $value)
        {
        if (!defined (get_class($this) . '::' . $name)

        Unknown macro: { throw new Zend_Exception (); // something like "unkown error" }

        $code = constant ($name);
        // something else
        }
        }]]></ac:plain-text-body></ac:macro>

        <p>On the other hand the exceptions will inherit the exception-codes from theire parents, so ... i dont really know, but so its possible to throw exceptions, with wrong component-codepart.</p>

        1. Sep 28, 2007

          <p>This would be no problem...</p>

          <p>Because the exception codes are unique. Each component has it's own 12 bits 0x021 in our example... and the other 12 bits should also be unique per component.</p>

          <p>I dont think that an class has to throw more than 4096 exceptions <ac:emoticon ac:name="smile" /></p>

          <p>The $e->StringTooLongException should not throw an new exception but only check if this exception hsa been thrown.</p>

          <p>I think we have to look that it's not possible to throw or recognise exceptions which are not from the called exception class. In my opinion inherited exceptions should not be allowed. This could lead to problematic useage and decrease useability.</p>

          <p>Btw: For now we are thinking about details for the proposal... if we use __call or not is for now not relevant. We should be consistent in what we want and then think about how to implement. <ac:emoticon ac:name="smile" /></p>

          1. Sep 28, 2007

            <p>Great ideas, everyone.</p>

            <p>To fill out the <code>__call()</code> idea:</p>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            class Zend_Exception extends Exception
            {
            /** @const integer Unknown exception */
            const UNKNOWN = 0x001000;

            /**

            • Returns an exception code given a valid method name.
              *
            • @param string $exceptionName Exception name (as a method call)
            • @return integer Exception code
              */
              public function __call($exceptionName, $value = null)
              Unknown macro: { return ($this->_getConstant($exceptionName) === $this->code); }

            /**

            • Retrieves a constant given an exception name.
              *
            • @param string $exceptionName Exception name
            • @return integer Exception code
              */
              protected function _getConstant($exceptionName)
              Unknown macro: { $constantName = get_class($this) . '}

            /**

            • Converts exceptionName to EXCEPTION_NAME.
              *
            • @param string $exceptionName Unformatted exception name
            • @return string Formatted exception name
              */
              protected function _formatAsConstant($exceptionName)
              Unknown macro: { $parts = preg_split('/([A-Z][a-z0-9]+)/', $exceptionName, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); return strtoupper(implode('_', $parts)); }

              }

            class Zend_Validate_Exception extends Zend_Exception
            {
            /** @const integer String too long exception */
            const STRING_TOO_LONG = 0x021010;

            /** @const integer String too short exception */
            const STRING_TOO_SHORT = 0x021011;
            }
            ]]></ac:plain-text-body></ac:macro>

            <p>Here's some test code, if you're curious:</p>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            // This should print '"Some string" is too short'
            try {
            throw new Zend_Validate_Exception('"Some string" is too short', 0x021011);
            } catch (Exception $e) {
            if ($e->stringTooShort())

            Unknown macro: { print $e->getMessage(); }

            else

            Unknown macro: { print 'No dice'; }

            }

            // This should print 'Some unknown exception'
            try {
            throw new Zend_Exception('Some unknown exception', 0x001000);
            } catch (Exception $e) {
            if ($e->unknown())

            else

            Unknown macro: { print 'No dice'; }

            }

            // This should throw an uncaught exception
            try {
            throw new Zend_Exception('Some unknown exception', 0x001000);
            } catch (Exception $e) {
            if ($e->bla())

            Unknown macro: { print $e->getMessage(); }

            else

            }
            ]]></ac:plain-text-body></ac:macro>

            1. Sep 28, 2007

              <p>Nice... I like it <ac:emoticon ac:name="wink" /></p>

              <p>Now we can do something like this:</p>
              <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
              try {
              throw new Zend_Validate_Exception('"Some string" is too short', 0x021011);
              } catch (Exception $e) {
              switch ($e->getCode())

              Unknown macro: { case $e}

              }
              ]]></ac:plain-text-body></ac:macro>

              <p>Now we need two more things...</p>

              <p>*) A way to give and store the values so we can seperate them from the exception<br />
              *) The translation itself...</p>

              <p>For the values we can add a getValue() function, but it's not really needed. We only have to store them internally for later at translation.</p>

              <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
              try {
              throw new Zend_Validate_Exception("String '%1\$s' too long", 0x021011, 'mystring');
              } catch (Exception $e) {
              print $e->getTranslatedMessage(); // could return "String 'mystring' ist zu groß"
              }
              ]]></ac:plain-text-body></ac:macro>

              <p>It would be great it we could do $e->getMessage($locale); but as getMessage is defined as final there is no way <ac:emoticon ac:name="sad" /></p>

              <p>Anyway... I think we can already add the proposed changes to the proposal itself. <ac:emoticon ac:name="smile" /></p>

          2. Sep 28, 2007

            <p>My (next) personal idea: One code of each exception-class is reserved as "unknownError", so maybe the last one 0xFFF. So something like this is possible</p>
            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[class Zend_Bla_Exception extends Zend_Exception
            {
            public function __construct ($name, $code = 0x012FFF)
            {
            if (($code < 0x012000) || ($code > 0x012FFF))

            Unknown macro: { $code = 0x012FFF; }

            }
            }]]></ac:plain-text-body></ac:macro>
            <p>On this way you can say "oh, ok, there where an error, but its code were out of range or not defined yet", but there is no possibility to get an error-code from a parent-class. Im agree with Thomas, that inherited error-codes would be confusing, especially when they are translated into readable text and return irritating messages not fitting to the exception-class currently thrown.</p>

            1. Sep 29, 2007

              <p>Makes sense...</p>

              <p>This way errors due to missing Exception Code or an forgotten Exception definition within the Exception class would throw an component exception and not a general one.</p>

              <p>But we should also catch undefined exceptions.</p>

              <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
              class Zend_Bla_Exception extends Zend_Exception
              {
              const MIN = 0x012000;
              const STRING_TOO_LONG = 0x012001;
              const STRING_TOO_SHORT = 0x012002;
              const MAX = 0x012003;
              const UNKNOWN = 0x012FFF;

              public function __construct ($name, $code = 0x012FFF) // handles forgotten exception code
              {
              if (($code <= self::MIN) ||($code >= self::MAX))

              Unknown macro: { $code = self}

              }
              }
              ]]></ac:plain-text-body></ac:macro>

              <p>Maybe there's a way to iterate through the defined class constants but not it's parents. Then we could do this instead of the min/max way.</p>

              <p>And also the method _getConstant() should return the UNDEFINED exception instead of creating a new generic exception. This way the exception is sure to be thrown in it's own class and not rethrown which could lead to unpredictible workflow.</p>

        2. Jun 26, 2008

          <p>Think this through for a minute; look at what you're doing here. First, you define a method, <code>StringTooLongException()</code>, that presumably returns a boolean indicating whether or not the current object is a "StringTooLong" exception. Then, you (rightfully) worry about the possibility of calling one if these identifying methods on the wrong exception class, thereby causing a fatal error "Call to undefined method". So, to solve that problem, you use a magic method and some name inflection code (along with its associated input validation), just to throw yet another Exception if the validation fails. That's an awful lot of work, just to replicate what PHP can automatically do for you with an appropriately named class.</p>

          <p>All you're trying to do in this example is just identify the exception, so you know what to do with it. You can achieve that goal far more simply like this:</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          // Extend Zend_Exception or Zend_Validate_Exception as appropriate
          class Zend_Validate_StringTooLongException extends Zend_Validate_Exception {
          ...
          }

          try {
          ...
          } catch (Zend_Validate_StringTooLongException $e) {
          // No need for an extra if or switch statement. $e is guaranteed to be an object of the correct exception class.
          ...
          }
          ]]></ac:plain-text-body></ac:macro>

          <p>This way, you don't need to write or maintain all that extra code to identify exceptions. Let the language do its job of handling that for you. If you try, for example, to catch a non-existent exception class, PHP will tell you right away with a "Class not found" error. Why over-complicate it?</p>

  8. Oct 01, 2007

    <p>Hi everyone,</p>

    <p>I've updated the proposal to incorporate all feedback I've received so far. I've also added Thomas as a co-author.</p>

    <p>Thomas, could you edit the <code>getTranslatedMessage()</code> method to work?</p>

    <p>Thanks,</p>

    <p>-Matt</p>

    1. Oct 02, 2007

      <p>Getting closer...</p>

      <p>Thomas, I've modified <code>getTranslatedMessage()</code> slightly so that it will pull translated messages from each component. I wasn't sure if it was an oversight or not as originally written. If you intended all the .mo files to reside under <code>Zend/Exception/</code> so it is easy on the translators, let me know and I'll change it back.</p>

      <p>Also, could you add example usage for the translation functionality on the user side and the framework side?</p>

      <p>Thanks,</p>

      <p>-Matt</p>

      1. Oct 03, 2007

        <p>My opinion was that's its better to have all "Exception" related translation under Zend_Exception.</p>

        <p>It makes not only live easier for the translators but also for others who want to give their own translation files instead of the original ones.</p>

        <p>But even with my opinion there are different ways to do it.</p>

        <ul>
        <li>We can do ONE file per language for all translations ('en.mo', 'de.mo', 'ar.mo'...). This was the original idea I had. This would mean less files and only one file for translation...</li>
        </ul>

        <ul>
        <li>We can do one file per class in one directory. Then we would have a structure like this... 'Zend_View.en.mo', 'Zend_View.de.mo',...</li>
        </ul>

        <ul>
        <li>We can do one file per class in one directory per language. Then we would have a structure like this... 'Zend/Exception/en/Zend_View.mo', 'Zend/Exception/de/Zend_View.mo'...</li>
        </ul>

        <p>I think the last one is the best from the point of usability and most logical.<br />
        Any other opinions ?</p>

        <p>And I will add an example for how to use...</p>

        <ul class="alternate">
        <li>Thomas</li>
        </ul>

        1. Oct 03, 2007

          <p>Thanks for the use cases. I've made a couple of small changes to make them a bit more clean and readable.</p>

          <p>I like the third option best as well. I've implemented it, except I left off the redundant "Zend" prefix. Files would just be <code>Zend/Exception/en/View.mo</code>. I've also added some parameters and a method to make userland subclassing easier. I think there's a lot of value in extending this class for application-level exceptions, so now users have the option of specifying base path, translation format, and file extension. This would work for framework authors as well, but I think there should be a standard format for all framework translations.</p>

          <p>Like you said in March, we must consider that doing this requires all component authors to become familiar with whatever translation format is used. Therefore it might not be best to use .mo. Also, unless we want to depend on <code>Zend_Translate</code> as an integral part of exception handling, translated exceptions will require the English exception to match both in the code and in the translation file as it stands currently. What are your thoughts on this?</p>

          <p>Finally, there needs to be a way to honor <code>setlocale()</code> and <code>Zend_Locale::FRAMEWORK</code> (or <code>ENVIRONMENT</code>) without passing in a locale object every single time you handle an exception. Is there a static method that allows you set a default locale for the duration of a request?</p>

          <p>Thanks</p>

          1. Oct 03, 2007

            <p>In my opinion the whole original Zend Framework should include only ONE format for all classes under the same directory structure.</p>

            <p>We can also use CSV or TMX as adapter, I am not fixed to GETTEXT.<br />
            But all classes should use the same format.</p>

            <p>Related to Zend_Translate... It is only then required and needed when "getTranslatedMessage()" is called. All normal code which was written until now has not to be changed.</p>

            <p>Related to the english translation... it would not be needed to have this one. But it's more consistent... this makes life easier for all who have to translate it into other languages. They would not have to search the code for all exceptions...</p>

            <p>Related to MessageIDs... it would not make sense to use messageIDs which are not equal with the exceptiontext. If someone forgets to translate an exception it would not show up with the right translation and be useless in this case. And speaking exception content makes life much easier.</p>

            <p>So the English Exception is not needed for translation but more for our translation-team. I would include it for every format which we would include, not only for gettext.</p>

            <p>Related to setlocale... you can eighter give nothing 'null' as locale. This let's Zend_Locale search for the best matching locale. Or you can give the locale 'auto' or 'browser' or 'environment' depending on your needs.<br />
            You can also use Zend_Locale::ENVIRONMENT or Zend_Locale::BROWSER.<br />
            Btw: You dont need to give a locale object... a simple text-representation is enough... 'en' instead of $locale = new Zend_Locale('en');</p>

            <ul class="alternate">
            <li>Thomas</li>
            </ul>

  9. Oct 04, 2007

    <p>I'm going to have to be the Devil's advocate on this one... I honestly think this is really bad case of misplaced responsibility. Surely you see that you're adding a ton of code to all the exceptions; they will go from small, light, easy-to-create objects, to large, complex difficult-to-create objects. So complex, in fact, that you have to invent a way to deal with errors inside the error handling "system". Since you have such a complex numbering system, you can't just throw an exception; it has to be the right code, or all sorts of non-intuitive things start happening.</p>

    <p>And how do you justify all this added code? Just so exception messages can be translated? Correct me if I'm wrong, but why else would you want to translate exception error messages if not to display them directly to the end user of the application you're writing? And if that is, in fact, the goal, then I strongly feel like that's a blatant misuse of exception messages in the first place. Exceptions are for the <strong>programmer</strong>, not the user, to signal him that something rare and unexpected happened. Something that would not normally happen, but must be checked for just in case (such as losing a database connection). Many of the examples above look like something straight out of the validation error messages used by Zend_Validate_* classes, and the cited conditions are just like user-input validation scenarios; none of which are appropriate problem domains for exceptions to solve, IMHO. The Zend_Validate_* classes do not throw exceptions with the validation errors embedded in their descriptions, and nor should they.</p>

    <p>As for the programmer, I believe the simplest and most usable code would be to just catch the right exception class name. It's very simple, easy to read, and built in to PHP. And it prevents from having to reinvent that very same wheel with a bunch of error codes and switch statements. We stopped writing procedural code and returning error codes from functions a long time ago, for good reasons.</p>

    <p>How exactly is this:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    try

    Unknown macro: { $date = new Zend_Date('Invalid input'); }

    catch (Zend_Date_Exception_InvalidInput $e) {
    $input = time();
    } catch (Zend_Date_Exception_NoTimezone $e) {
    $date->setTimezone(date_default_timezone_get());
    } catch (Zend_Date_Exception_NoLocale $e) {
    print 'No locale was found. Please configure your browser.';
    } catch (Zend_Date_Exception $e) {
    // Substitute the correct API here; I don't know it at the moment...
    print $translator->_($e->getMessage());
    } catch (Zend_Exception $e) {
    print $e->getMessage();
    }
    ]]></ac:plain-text-body></ac:macro>
    <p>...harder to read or maintain than this:-</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    try {
    $date = new Zend_Date('Invalid input');
    } catch (Zend_Date_Exception $e) {
    switch ($e->getCode())

    Unknown macro: { case Zend_Date_Exception}


    }
    ]]></ac:plain-text-body></ac:macro>
    <p>?</p>

    <p>And given the fact that an effective numbering scheme for exceptions is so difficult to come up with, I think it makes more sense to just scrap it. The framework is going to be constantly evolving; new components will be added, old ones deprecated... Over time, any sort of consecutive numbered scheme is going to cause more headaches than it's worth. Not to mention the up-front issues of numbering space. If they're going to be given any kind of code, the exceptions really need something stable like their own GUIDs. There are several downsides to those, also, but I think you see my point.</p>

    <p>Finally, all this is just my opinion. Take from it what you will.</p>

    1. Oct 04, 2007

      <p>Hi Bryce,</p>

      <p>To address your points one by one:</p>

      <blockquote>
      <p>Surely you see that you're adding a ton of code to all the exceptions; they will go from small, light, easy-to-create objects, to large, complex difficult-to-create objects. So complex, in fact, that you have to invent a way to deal with errors inside the error handling "system". Since you have such a complex numbering system, you can't just throw an exception; it has to be the right code, or all sorts of non-intuitive things start happening.</p></blockquote>

      <p>Small, light, and not particularly useful for anything except knowing that an exception was thrown. I think we agree on this.</p>

      <p>This is an example exception under the proposed new system:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      class Zend_Example_Exception extends Zend_Exception
      {
      /** @const integer Exception code range assigned to this component */
      const ASSIGNED_RANGE = 0xFFF000;

      /** @const integer Unknown exception */
      const UNKNOWN = 0xFFF000;

      /** @const integer Example exception */
      const EXAMPLE = 0xFFF001;
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>Authors would throw an exception like this:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      throw new Zend_Example_Exception('Example exception', Zend_Example_Exception::EXAMPLE);
      ]]></ac:plain-text-body></ac:macro>

      <p>Or this:</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      throw new Zend_Example_Exception('Example value %1\$s', Zend_Example_Exception::EXAMPLE, $value);
      ]]></ac:plain-text-body></ac:macro>

      <p>This does not seem prohibitively difficult to me. You are passing in a constant, not the integer itself.</p>

      <blockquote>
      <p>And how do you justify all this added code? Just so exception messages can be translated?</p></blockquote>

      <p>The justification is outlined in the four points in the proposal. Under this new model users can:</p>

      <ol>
      <li>Distinguish exceptions based on the type of error instead of only by component.</li>
      <li>Make special casing more readable using method calls.</li>
      <li>Translate exceptions into their own language. Not all programmers speak English; the ones that do would probably prefer exceptions in their own language.</li>
      <li>Potentially visit a website with the exception code and see possible solutions and comments from other users.</li>
      </ol>

      <p>Furthermore, this proposal is intentionally designed to be implemented in stages, so that authors can gradually move to the new system instead of all at once.</p>

      <blockquote>
      <p>How exactly is this ... harder to read or maintain than this ...?</p></blockquote>

      <p>This is a matter of personal preference, although the second example seems more clear to me.</p>

      <p>Beyond that, there are practical reasons for this as well. With the proposed method, I can cover many different types of exceptions with one statement.</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      switch ($e->getCode()) {
      case Zend_Example_Exception::SOME_ERROR:
      // Fall through
      case Zend_Example_Exception::SOME_SIMILAR_ERROR:
      print 'something';
      break;
      case ...
      }
      ]]></ac:plain-text-body></ac:macro>

      <p>This is impossible with a <code>try</code>/<code>catch</code> block.</p>

      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      php > class TestException extends Exception {}
      php > class TestException2 extends TestException {}
      php > try {
      php { throw new TestException2('Error');
      php { } catch (TestException $e) {
      php { print 'TestException';
      php { } catch (TestException2 $e) {
      php { print 'TestException2';
      php { }
      TestException
      ]]></ac:plain-text-body></ac:macro>

      <blockquote>
      <p>And given the fact that an effective numbering scheme for exceptions is so difficult to come up with, I think it makes more sense to just scrap it. The framework is going to be constantly evolving; new components will be added, old ones deprecated... Over time, any sort of consecutive numbered scheme is going to cause more headaches than it's worth. Not to mention the up-front issues of numbering space. If they're going to be given any kind of code, the exceptions really need something stable like their own GUIDs. There are several downsides to those, also, but I think you see my point.</p></blockquote>

      <p>Well, a numbering scheme isn't really that difficult to come up with. In my initial proposal I threw something out there to get people talking, and we arrived at a consensus. I'm also not clear on how one would cause headaches. The only people who will interact with the hex values are the component authors, who will only use them to add new exception types. After that they would use the constant values exclusively.</p>

      <p>There are 4096 possible component values in the scheme, with 4096 possible exception types per component. I think this should be a sufficiently large enough range-16.8 million possible values-to allow globally-unique identifiers if that is deemed desirable. However, because no one is interacting with the integer values directly (except for the component author when they initially create the exception), these values could conceivably be changed with no negative repercussions.</p>

      <p>Thanks for taking the time to respond to this proposal. Any and all feedback is appreciated. <ac:emoticon ac:name="smile" /></p>

      <p>-Matt</p>

      1. Oct 05, 2007

        <p>There's nothing like a good healthy argument. <ac:emoticon ac:name="smile" /> I don't think what you're doing with this is entirely evil; I'll just chalk the our differences up to, like you mentioned, personal preference.</p>

        <p>I just prefer to have a descriptive class name instead of having to type out the class name and long class constants. I know you can't do the fall through with catch blocks, but I don't find I need to do that much.</p>

        <p>Oh well, at least I spoke my piece. <ac:emoticon ac:name="smile" /></p>

    2. Jun 13, 2008

      <p>I totally agree with Bryce.</p>

      <p>I think this way to handle exceptions is a misunderstanding of how exceptions are meant to be used. (cf. <a class="external-link" href="http://loveandtheft.org/2008/05/23/exceptions-youre-doing-it-wrong/">http://loveandtheft.org/2008/05/23/exceptions-youre-doing-it-wrong/</a>)</p>

      <p>I understand that the codes you want to add would fix part of this problem but I think it is not the right answer to this problem.</p>

      <p>IMHO, the limitation you point out regarding the catch block is more a PHP problem that should be fixed at the language level than at the ZF one.</p>

      1. Jun 13, 2008

        <p>So instead of making it better as it actually works, you propose to let all things as bad as they are ?</p>

        <p>If we would work this way we would not have build ZF.<br />
        We can not change the language, how could we ? We are the ZF team and not the PHP dev-team.</p>

        <p>As long as this is not possible at language level it's in my opinion always better to have features and inventions solved in another way.</p>

        1. Jun 13, 2008

          <p>Hello Thomas,</p>

          <p>I do not understand why you are so rude with people who does not agree with this proposal. I was only expressing my humble opinion. I believe this is why this proposal is for, isn't it ?</p>

          <p>Regarding the proposal itself, I think it is an overcomplicated way that solve a non-issue.</p>

          <p>> First, it's now possible to distinguish exceptions based on the type of error instead of only by class. This allows users to handle them intelligently.<br />
          I do not see why would this be more intelligent.</p>

          <p>> Second, codes let us do some interesting things with exception handling. Users would now be able to call a method such as<ac:link><ri:page ri:content-title="..." /></ac:link> thereby making exception special-casing easy.<br />
          That's a good point but I think this should be handled at PHP level.</p>

          <p>> Third, this gives us the ability to translate error messages using Zend_Translate (loaded only when an exception occurs) and using separate translation files (for example, .mo format). Not all developers speak English; those that do generally prefer to see exception messages in their native language.<br />
          I do not think this should be important since, as someone said earlier, exceptions are not meant for end user display. But if this is a concern for you, it can be done using class inheritance.</p>

          <p>> Finally, users could potentially visit something like <a class="external-link" href="http://framework.zend.com/exceptions/0xFFFFFF">http://framework.zend.com/exceptions/0xFFFFFF</a><br />
          Why using cryptic codes would be better than using meaningful class names ?</p>

          <p>Once again this is just my opinion. Do not take it personally. <ac:emoticon ac:name="wink" /></p>

          1. Jun 13, 2008

            <blockquote>
            <p>I do not understand why you are so rude with people who does not agree with this proposal. I was only expressing my humble opinion. I believe this is why this proposal is for, isn't it ?</p></blockquote>
            <p>I apologize if you think that I was rude. It is sometimes hard for a non native english to understand the complete meaning.</p>
            <blockquote>
            <p><em>Also am describing what I expect to add, otherwise I would not helped with this proposal.First, it's now possible to distinguish exceptions based on the type of error instead of only by class. This allows users to handle them intelligently.</em></p>

            <p>I do not see why would this be more intelligent. </p></blockquote>
            <p>This is exactly what is described in your link as must.</p>
            <blockquote>
            <p>That's a good point but I think this should be handled at PHP level.</p></blockquote>
            <p>So instead of solving this now we should wait for PHP 9 ? We are not the makers of PHP <ac:emoticon ac:name="wink" /></p>

            <blockquote>
            <p>I do not think this should be important since, as someone said earlier, exceptions are not meant for end user display. But if this is a concern for you, it can be done using class inheritance.</p></blockquote>
            <p>But that's exactly what proposals are for... invent and propose new ideas. It is clear that all native english will not use this feature.<br />
            But for all non native english it has real benefits.</p>

            <p>It allows also an other additional thing... you could change the exception message to be translated to something else... for example a exception "Database xxx not found" could be translated to "Can not connect to database".<br />
            Because sometimes it IS usefull to display defined exception messages to users (administrators).</p>

            <blockquote>
            <p>Why using cryptic codes would be better than using meaningful class names ?</p></blockquote>

            <p>Why not support both ? Sometimes it is simply usefull to have codes instead of names.</p>

            <p>As ZF developer I always tend to have a multitude of possibilities supported instead of just the default way. Keep it simple but allow special ways if someone needs them.</p>

            1. Jun 14, 2008

              <p>> It is sometimes hard for a non native english to understand the complete meaning.</p>

              <p>I understand that english not being my mother tongue. <ac:emoticon ac:name="wink" /></p>

      2. Jun 13, 2008

        <p>Hi Jean-Marc,</p>

        <p>Thanks for the feedback. I read the blog article you linked to, and while this is a <em>current</em> issue with Zend Framework, this is the reason for our proposal and we feel it addresses the issue completely. Actually, if you read the comments, <a href="http://loveandtheft.org/2008/05/23/exceptions-youre-doing-it-wrong/#comment-282">they agree with us</a>. So I'm afraid I must disagree with your assessment. After all, PHP provides an error code parameter in Exception for a reason. <ac:emoticon ac:name="wink" /></p>

        1. Jun 14, 2008

          <p>Hello Matthew,</p>

          <p>> After all, PHP provides an error code parameter in Exception for a reason. <br />
          That's a good point but to be true, I do not understand what is this code for. <ac:emoticon ac:name="smile" /></p>

          <p>BTW, Zend_View_Exception receives a Zend_View object as the second argument of its constructor :</p>

          <p>public function __construct($message, Zend_View_Interface $view = null)</p>

          <p>Maybe some other exceptions behave the same. That will be an issue when implementing your proposal.</p>

          1. Jun 14, 2008

            <blockquote>
            <blockquote><p>After all, PHP provides an error code parameter in Exception for a reason. </p></blockquote>
            <p>That's a good point but to be true, I do not understand what is this code for. <ac:emoticon ac:name="smile" /></p></blockquote>

            <p>The error code parameter is intended to be used exactly how we're using it: differentiating exceptions within exception "namespaces" (classes).</p>

            <blockquote>
            <p>BTW, Zend_View_Exception receives a Zend_View object as the second argument of its constructor :</p>

            <p>public function __construct($message, Zend_View_Interface $view = null)</p>

            <p>Maybe some other exceptions behave the same. That will be an issue when implementing your proposal.</p></blockquote>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            public function __construct($message = null, $code = 0)
            {
            $params = func_get_args();
            $view = max($params);
            if ($view instanceof Zend_View_Interface)

            Unknown macro: { $this->view = $view; array_pop($params); }

            parent::__construct($message, $code, $params);
            }
            ]]></ac:plain-text-body></ac:macro>

  10. Oct 15, 2007

    <p>Hy matthew and everyone,</p>

    <p>I think the proposal looks good and finished.<br />
    All needed points have been cleared and integrated.</p>

    <p>I would propose that we go the next step to let the proposal be reviewed by the dev-team.<br />
    Let's switch from new to review. <ac:emoticon ac:name="smile" /></p>

    <p>Opinions ?</p>

    1. Oct 15, 2007

      <p>I think this sounds great, and I wanted to make sure that the drivers of this proposal know that the Zend team would review this after the community has had a good chance to review first. I think this has already happened, at least for the most part, but if another community review is desirable for whatever reasons, please don't hesitate to call for one on the mailing list(s). If we are indeed ready for Zend team review, please let me or another Zendian know to schedule it. <ac:emoticon ac:name="smile" /></p>

      <p>Thanks to all for your feedback and efforts on this proposal!</p>

      1. Oct 15, 2007

        <p>Of course, we'll need a working wiki for this, too. <ac:emoticon ac:name="smile" /> Hopefully we'll have a solution for the "<code>Error formatting macro: zone-template-instance: java.lang.NullPointerException</code>" problem very soon. <ac:emoticon ac:name="sad" /></p>

        1. Mar 03, 2008

          <p>I also think this is a "must have". For example the Zend_Auth_Result class - I have to catch all errors by myself to add a translation for the failure I could directly present the user. This option would allow me to have easier controle about what the application does and what I can show the end-user.</p>

  11. Oct 19, 2007

    <p>A question about the proposed numbering scheme: who is responsible for assigning exceptions codes and enforcing uniqueness? Suppose I'm a working a new DB adapter, for example, and I identify three different conditions where I need to throw an exception. I would need three exception codes, one per message (for translation, right?) OK, so while I'm doing this, say Bill K. happens to identify three new conditions where exceptions should be thrown in Zend_Db_Table. If we both manually search through all of the Zend_Db code around the same time, we're very likely to use the same numbers. Even if developers are vigilent about checking for unique codes before committing, there's still a huge window of error. Multiply that by developers scattered all over the world, with people checking and committing with unknown time intervals, and it should be obvious that there's a problem. It's very much like trying to get the next value from a database sequence, with all the same concurrency problems, only much worse, since there's no DB to automate it and much larger frames of time.</p>

    <p>Also, there are only two "namespace" levels in the proposed scheme; component and class. Many existing components have "subcomponents" right now, Zend_Db and Zend_Auth being good examples, and they are both intended to be expanded in the future. As these and other components grow (especially after the introduction of real namespaces to PHP), that 2-level exception number space will be more and more of a limitation.</p>

    <p>And, are you really sure you want to force everyone to do all the extra typing that having all those class contants and multiple constructor parameters is going to require?</p>

    <p>Feel free to disagree with me, but I at least wanted to raise the issue one last time. <ac:emoticon ac:name="smile" /></p>

    1. Oct 20, 2007

      <blockquote>
      <p>A question about the proposed numbering scheme: who is responsible for assigning exceptions codes and enforcing uniqueness? Suppose I'm a working a new DB adapter, for example, and I identify three different conditions where I need to throw an exception. I would need three exception codes, one per message (for translation, right?) OK, so while I'm doing this, say Bill K. happens to identify three new conditions where exceptions should be thrown in Zend_Db_Table. If we both manually search through all of the Zend_Db code around the same time, we're very likely to use the same numbers. Even if developers are vigilent about checking for unique codes before committing, there's still a huge window of error. Multiply that by developers scattered all over the world, with people checking and committing with unknown time intervals, and it should be obvious that there's a problem. It's very much like trying to get the next value from a database sequence, with all the same concurrency problems, only much worse, since there's no DB to automate it and much larger frames of time.</p></blockquote>

      <p>This is really no problem at all. We are all working with SVN. All exceptions which are raised within a class have to be defined within the exception class. For your example this would be "Zend_Db_MyClass_Exception". If you forgot to add your exception to the exception class and another coder uses the exceptioncode you whished to add, you will have to change your code when you add it to the exception class to the code you added to the exception class.</p>

      <p>All you have to check is the exception class, not the complete code. If the exception has not been added to the exception class you will get an CODE_OUT_OF_RANGE or an UNKNOWN exception.</p>

      <blockquote>
      <p>Also, there are only two "namespace" levels in the proposed scheme; component and class. Many existing components have "subcomponents" right now, Zend_Db and Zend_Auth being good examples, and they are both intended to be expanded in the future. As these and other components grow (especially after the introduction of real namespaces to PHP), that 2-level exception number space will be more and more of a limitation.</p></blockquote>

      <p>The new coding standard defines only the main component part and the class part. If a class has many subcomponents like Zend_Db the main author (Bill) would be responsible for defining which subcomponent uses which range within the component range. For example 0x001001-0x001029 for Zend_Db, 0x0010030-0x001059 for Zend_Db_Adapter and so on...</p>

      <p>The only limitation is that there are only 4096 exceptions per main component. Do you think that a component will have more than 4096 exceptions ? I don't <ac:emoticon ac:name="wink" /></p>

      <blockquote>
      <p>And, are you really sure you want to force everyone to do all the extra typing that having all those class contants and multiple constructor parameters is going to require?</p></blockquote>

      <p>There is not much extra typing.<br />
      Example:</p>
      <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
      // within the exception class
      const MY_EXCEPTION = 0x047007;

      // within the class throwing the exception
      throw new Zend_MyClass_Exception("My text to throw", 0x047007);
      ]]></ac:plain-text-body></ac:macro>

      <p>The only change to the old coding standard is, that the coder has think a little bit more when he adds a new exception instead of just write what comes in his mind.</p>

      <p>The real benefit has the user. He is able to switch through the exceptions or translate the content.</p>

      <blockquote>
      <p>Feel free to disagree with me, but I at least wanted to raise the issue one last time.</p></blockquote>

      <p>You asked for it <ac:emoticon ac:name="wink" /></p>

      1. Oct 22, 2007

        <blockquote>
        <p>For example 0x001001-0x001029 for Zend_Db, 0x0010030-0x001059 for Zend_Db_Adapter and so on...</p></blockquote>

        <p>A bit easier would be 0x001000-0x0010FF, 0x001100-0x0011FF, etc. for division within a component. To minimize micromanagement, however, that should be determined by the coordinator for that component by however is internally convenient.</p>

        <blockquote>
        <p>Example:</p>
        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        // within the exception class
        const MY_EXCEPTION = 0x047007;

        // within the class throwing the exception
        throw new Zend_MyClass_Exception("My text to throw", 0x047007);
        ]]></ac:plain-text-body></ac:macro></blockquote>

        <p>I think we want to strongly discourage authors from using the error codes directly. It might even be worthwhile to make that a part of the coding specification.</p>

        <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
        throw new Zend_MyClass_Exception('My text to throw', Zend_MyClass_Exception::MY_EXCEPTION);
        ]]></ac:plain-text-body></ac:macro>

        <p>is honestly not that big of a deal to type, and is much easier to read than magic numbers.</p>

        1. Oct 22, 2007

          <blockquote>
          <p>I think we want to strongly discourage authors from using the error codes directly. It might even be worthwhile to make that a part of the coding specification.</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          throw new Zend_MyClass_Exception('My text to throw', Zend_MyClass_Exception::MY_EXCEPTION);
          ]]></ac:plain-text-body></ac:macro></blockquote>

          <p>Of course you're right.</p>

          <p>And we both agree that it's not much what the coder would have to add for an exception. <ac:emoticon ac:name="wink" /></p>

        2. Jun 26, 2008

          <p>The way I see it</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          throw new Zend_MyClass_Exception('My text to throw', Zend_MyClass_Exception::MY_EXCEPTION);
          ]]></ac:plain-text-body></ac:macro>
          <p>is functionally identical to</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          throw new Zend_MyClass_MyException('My text to throw');
          ]]></ac:plain-text-body></ac:macro>
          <p>with respect to identifying which specific exception has been thrown. And:</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          catch {Zend_MyClass_Exception $e) {
          if ($e->myException())

          Unknown macro: { ... }

          }
          ]]></ac:plain-text-body></ac:macro>
          <p>is more complex (granted, not by a large margin, but true nontheless) than:</p>
          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          catch (Zend_MyClass_MyException $e) {
          ...
          }
          ]]></ac:plain-text-body></ac:macro>

          <p>As far as I can tell, the only functionality the extra complexity buys you is the use of a switch statement in the catch block, which I don't see as a particularly strong argument. (Note that I'm not addressing the translation functionality; I see that as a separate issue.)</p>

          <p>It's my opinion that the extra procedural-style code-checking is a very unintuitive and uncomfortable thing to have to do in an otherwise strong OOP environment.</p>

      2. Oct 31, 2007

        <blockquote>
        <p>All exceptions which are raised within a class have to be defined within the exception class.</p></blockquote>
        <p>I'm not quite sure what you mean by this. I interpret that as "All exception codes within an exception class must be defined within that same class, as integer constants". Is that correct?</p>

        <blockquote>
        <p>If you forgot to add your exception to the exception class and another coder uses the exceptioncode you whished to add, you will have to change your code when you add it to the exception class to the code you added to the exception class.</p></blockquote>
        <p>I assume here you're talking about the integer exception code values. If that's true, then my concern is about having duplicate integer values in different exception classes within the same component. For example, Zend_Db's range is 0x001. There's nothing to prevent both Zend_Db_MyFirstException and Zend_Db_MySecondException from both using value 0x001001 for completely different purposes. Manual programmer diligence is the only way, which is both tedious and very unreliable (see my original argument about the concurrency problems with this).</p>

        <p>Both of those exception classes will work completely fine with their duplicate codes; they don't care that they happen to be using the same code. But it will be a problem when somebody tries to go to <a class="external-link" href="http://framework.zend.com/exceptions/0x001001">http://framework.zend.com/exceptions/0x001001</a> (for example), because the codes are expected to be unique across classes and aren't. Honestly, why not have the URL be <a class="external-link" href="http://framework.zend.com/exceptions/Zend_Db_MyFirstException/1">http://framework.zend.com/exceptions/Zend_Db_MyFirstException/1</a> (for example)? That would be more reliable, IMHO.</p>

        <blockquote>
        <p>All you have to check is the exception class, not the complete code. If the exception has not been added to the exception class you will get an CODE_OUT_OF_RANGE or an UNKNOWN exception.</p></blockquote>
        <p>Would you not have check <strong>ALL</strong> exception classes within the same component? Based on the descriptions and example exception above, that would seem to be the case to me. Some of the larger components may have quite a few exception classes to search through. Also, how does an exception with the UNKNOWN code get thrown? I didn't see any code in the proposal text that attempted to detect whether or not any given exception code is a valid, defined constant. I assume you meant to check the class part of the code against the current class's defined constants in the exception superclass.</p>

        <blockquote>
        <p>The new coding standard defines only the main component part and the class part. If a class has many subcomponents like Zend_Db the main author (Bill) would be responsible for defining which subcomponent uses which range within the component range. For example 0x001001-0x001029 for Zend_Db, 0x0010030-0x100059 for Zend_Db_Adapter and so on...</p>

        <p>The only limitation is that there are only 4096 exceptions per main component. Do you think that a component will have more than 4096 exceptions ?</p></blockquote>
        <p>I agree that it's quite unlikely that a given component will have 4k exceptions at one level deep; that seemed pretty obvious to me. My concern was with the numbering space as you go further down the component's sub-component hierarchy. In the framework's naming convention, every directory level is essentially a namespace, or package, that may contain any number of classes. In the example you cite, all exceptions in the Zend_Db_Adapter namespace get the range 0x001030-0x001059. That's 41 possible exceptions, which is likely acceptable for that specific namespace. But what about Zend_Db_Adapter_Pdo_Ibm? You now need to insert two more levels of sub-component division into the 12-bit space. My point is that as the framework grows, those bit ranges will artificially constrain the depth at which you can add new sub-components. Of course, the easy fix is to throw more bits at it, but the principle remains.</p>

        <blockquote>
        <p>There is not much extra typing.</p></blockquote>
        <p>There's a considerable amount of extra typing (IMO) if you use the class constants, as recommended, and as I was talking about originally.</p>

        <blockquote>
        <p>The real benefit has the user. He is able to switch through the exceptions or translate the content.</p></blockquote>
        <p>As I originally argued, if this results in a "real benefit" to end users of the applications built on the framework, then it's a misuse of exceptions. There is some benefit for the programmer, but again, is it worth the cost?</p>

        <p>All in all, I still think this is a noble cause that just happens to not be very feasible to implement.</p>

        1. Nov 01, 2007

          <blockquote><p>I'm not quite sure what you mean by this. I interpret that as "All exception codes within an exception class must be defined within that same class, as integer constants". Is that correct?</p></blockquote>

          <p>No...<br />
          You have to define the exceptions for Zend_Db within Zend_Db_Exception and not within Zend_Db...<br />
          And the constants are no integers, but longs.</p>

          <blockquote><p>I assume here you're talking about the integer exception code values. If that's true, then my concern is about having duplicate integer values in different exception classes within the same component. For example, Zend_Db's range is 0x001. There's nothing to prevent both Zend_Db_MyFirstException and Zend_Db_MySecondException from both using value 0x001001 for completely different purposes. Manual programmer diligence is the only way, which is both tedious and very unreliable (see my original argument about the concurrency problems with this).</p></blockquote>

          <p>So you think we should also take care of the subcomponents within that proposal and not only of the components itself ? We would then have to extend the codes with one or two digits for the subcomponents for the reason that programmers will not take care of the borders they get from the main author ?</p>

          <blockquote><p>Both of those exception classes will work completely fine with their duplicate codes; they don't care that they happen to be using the same code. But it will be a problem when somebody tries to go to <a class="external-link" href="http://framework.zend.com/exceptions/0x001001">http://framework.zend.com/exceptions/0x001001</a> (for example), because the codes are expected to be unique across classes and aren't. Honestly, why not have the URL be <a class="external-link" href="http://framework.zend.com/exceptions/Zend_Db_MyFirstException/1">http://framework.zend.com/exceptions/Zend_Db_MyFirstException/1</a> (for example)? That would be more reliable, IMHO.</p></blockquote>

          <p>We can not use URL because the Code has to be a long and not a string !!! The URL was just an idea to provide users with additional informations and use cases for raised exceptions and it was not part of the proposal itself.</p>

          <blockquote><p>Would you not have check ALL exception classes within the same component? Based on the descriptions and example exception above, that would seem to be the case to me. Some of the larger components may have quite a few exception classes to search through.</p></blockquote>

          <p>No, because each exception class for a component has it's defined border which the main author has to set.</p>

          <blockquote><p>Also, how does an exception with the UNKNOWN code get thrown? I didn't see any code in the proposal text that attempted to detect whether or not any given exception code is a valid, defined constant. I assume you meant to check the class part of the code against the current class's defined constants in the exception superclass.</p></blockquote>

          <p>No, you have not to check against UNKNOWN. This is done by Zend_Exception from which all exception classes have to be extended. The code is there... see method _getConstant().</p>

          <blockquote><p>The new coding standard defines only the main component part and the class part. If a class has many subcomponents like Zend_Db the main author (Bill) would be responsible for defining which subcomponent uses which range within the component range. For example 0x001001-0x001029 for Zend_Db, 0x0010030-0x100059 for Zend_Db_Adapter and so on...</p>

          <p>The only limitation is that there are only 4096 exceptions per main component. Do you think that a component will have more than 4096 exceptions ?</p></blockquote>

          <blockquote><p>I agree that it's quite unlikely that a given component will have 4k exceptions at one level deep; that seemed pretty obvious to me. My concern was with the numbering space as you go further down the component's sub-component hierarchy. In the framework's naming convention, every directory level is essentially a namespace, or package, that may contain any number of classes. In the example you cite, all exceptions in the Zend_Db_Adapter namespace get the range 0x001030-0x001059. That's 41 possible exceptions, which is likely acceptable for that specific namespace. But what about Zend_Db_Adapter_Pdo_Ibm? You now need to insert two more levels of sub-component division into the 12-bit space. My point is that as the framework grows, those bit ranges will artificially constrain the depth at which you can add new sub-components. Of course, the easy fix is to throw more bits at it, but the principle remains.</p></blockquote>

          <p>So you think we should not implement this proposal because the framework may grow in the future ???<br />
          I don't agree to this.</p>

          <p>And the size of the subcomponents are now defined through the main author. The question is, if we, as ZF-DEV Team should also take care of the subcomponents or if the main author should do this. The question is also if having one or two digits more for the subcomponent is acceptable or not...</p>

          <p>Btw: As matthew already wrote the border sizes are not fixed... it could also be 0x001001 - 0x001011 or even 0x001005...</p>

          <blockquote><p>There's a considerable amount of extra typing (IMO) if you use the class constants, as recommended, and as I was talking about originally.</p></blockquote>

          <p>Now authors don't have a rule on how to define exceptions. Most don't use codes but just write text. Having this implemented means to have a framework wide convention which is logical and leads the authors to write more readable code. It's clear that having this implemented the author must take care of the additional rule which means to have the exception constant to be written after the text. And exactly that was what many users were referring to... that most coders don't add codes to their exception. With that proposal coders must take care of it. </p>

          <blockquote><p>As I originally argued, if this results in a "real benefit" to end users of the applications built on the framework, then it's a misuse of exceptions. There is some benefit for the programmer, but again, is it worth the cost?</p></blockquote>

          <p>Are we building a framework just for fun ? Or are we building a framework for our users which will use it ? I think we should code this framework for those who use it and not for us. Of course our users are also coders, but I think the cost is acceptable related to the benefit we have.</p>

          <blockquote><p>All in all, I still think this is a noble cause that just happens to not be very feasible to implement.</p></blockquote>

          <p>Nothing to do means to ignore the wishes of the people which use this framework. All users which are native english will not have benefit for it. That's right... but all <strong>NON-ENGLISH</strong> will have.</p>

          <p>Maybe that's the reason for your opinion ? I am native german.<br />
          As this framework is intended to be world-wide accepted we should also take care for others <ac:emoticon ac:name="wink" /></p>

          1. Nov 06, 2007

            <p>First of all, let me apologize if my comments came across as combative. My intention is only to discuss this in a purely technical fashion.</p>

            <p>That said, I am still rather confused about what the real technical ramifications of this proposal will be on the rest of the framework. I've taken a fair swing and trying to understand it, and sharing my opinions based on that. Again, I'm not completely against the ideals represented here, but I believe at this point, it's unlikely I'm going to really "get it" as much as you.</p>

            <p>I'm going to close this discussion by saying that it would be nice if some others reviewed and commented on this, for a broader range of opinions, and in case I'm just completely off my rocker on this.</p>

            1. Nov 06, 2007

              <p>As a developer use case #4 should be reason enough, even for us mono-linguists <ac:emoticon ac:name="smile" /> </p>

              <p>Rationalising exceptions into a more manageable naming scheme is, IMO, a better way to handle either single or groups of exceptions and stops the possibility of overly-complex subclassing simply to handle specific instances (e.g. Zend_My_Component_Transport_Send_Logic_Exception extends Zend_My_Component_Transport_Send_Exception extends Zend_My_Component_Transport_Exception etc...)</p>

              1. Jun 26, 2008

                <p>I completely agree that the naming conventions for exception classes needs to be overhauled. And part of that should include reasonable guidelines against the kind of run-away namespace/directory nesting you describe. In practice, the overwhelming majority of exceptions can share a very shallow hierarchy under their component. Something like:</p>

                <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
                Zend_Example_Exception extends Zend_Exception
                Zend_Example_FileNotFoundException extends Zend_Example_Exception
                Zend_Example_FileAccessDeniedException extends Zend_Example_Exception
                Zend_Example_FileLockedException extends Zend_Example_Exception
                // and so on
                ]]></ac:plain-text-body></ac:macro>

                <p>Another very useful thing would to be have certain framework-wide general exceptions for common, recurring situations. A very common example is checking for missing method parameters, or for the correct format of a parameter. We could have a Zend_MissingArgException and/or Zend_InvalidArgFormatException or some similar such classes. These would be certainly much more descriptive than a generic Zend_Exception.</p>

  12. Jan 08, 2008

    <p>Hello</p>

    <p>Is there any date or any version for this functionality ? I check my exception with string parser, but if a date is announced all my project might be changed.</p>

    <p>On the french forum, we are some people to be very interrested by this functionality. All error and exception must be translate and it's sometimes a big work.</p>

    <p>Thanks<br />
    Pierre</p>

    1. Jan 08, 2008

      <p>Hi Pierre,</p>

      <p>This proposal is marked "ready for review", so it's really up to the Zend team at this point when and if this proposal is accepted. There's not much work involved to set the groundwork (what you see above is basically it), but the various Zend Framework components will have to be modified by each component owner and that will take time. Beyond that, translation work will have to be done, which is also not an insignificant task.</p>

      <p>For now, continue with the existing functionality. If and when this proposal is accepted, it will still probably take months to get everything ready.</p>

    2. Jan 08, 2008

      <p>Hy Pierre,</p>

      <p>Actually the proposal itself is ready for today from our point of view.</p>

      <p>The Dev-Team (that's wether Matthew, nor me <ac:emoticon ac:name="smile" /> ) is brainstorming the pro's and con's.<br />
      For now there are some issues which have to be defined in detail.</p>

      <p>I was said that this will not occur until the holidays have finished.<br />
      And when this is done the dev-team will write an response within here where Matthew and me can respond and take further progress.</p>

      <p>As Matthew said, this process, until all is implemented as requested and proposed will take several weeks. Since it's not only "coding" but also defining the proper coding details, documentation and so on...</p>

      <p>So for now you will have to use what exists...</p>

      <p>Btw: The more response to an proposal is written, the faster will the dev-team look to get it ready. <ac:emoticon ac:name="wink" /></p>

      1. Jan 11, 2008

        <p>Hi</p>

        <p>I asked myself, what happened to this proposal, while Im waiting. So now (as you mentioned) Ill make a response, so the dev-team will make it ready faster <ac:emoticon ac:name="smile" /></p>

        <p>I see gettext is prefered by default as the translation adapter. So will it give a pot-file for easier translation?</p>

        <p>Bye, Sebastian</p>

  13. Feb 21, 2008

    <p>The idea of error codes and a lookup page is great, I would really love to see that!</p>

    <p>But please... do NOT put translation mechanisms inside exceptions. Having code inside exceptions that can (even if the chances are remote) throw exceptions just doesn't make sense.</p>

    <p>I think the majority of developers speak (or at least read) English or will eventually. This for the simple reason that you just can't make it really far in the programming world without even a small bit of English.<br />
    Instead, I propose a translated lookup page: <a class="external-link" href="http://framework.zend.com/exceptions/en/0xFFFFFF">http://framework.zend.com/exceptions/en/0xFFFFFF</a> for English, <a class="external-link" href="http://framework.zend.com/exceptions/de/0xFFFFFF">http://framework.zend.com/exceptions/de/0xFFFFFF</a> for German.. etc.<br />
    This way you can provide more localized information in a much safer, cleaner and less resources consuming way.</p>

    1. Feb 21, 2008

      <p>Even so, you'd still need people to set their locale preference and then rely on that in the exception class in order to generate a relevant link.</p>

      1. Mar 03, 2008

        <p>Not necessarily... if you'd just link to <a class="external-link" href="http://framework.zend.com/exceptions/en/0xFFFFFF">http://framework.zend.com/exceptions/en/0xFFFFFF</a> and offer translated resources from there... Again, they're just exceptions. Things that in normal circumstances don't occur. Treat them as such.</p>

    2. Feb 21, 2008

      <p>I can say it just again and again...<ac:emoticon ac:name="smile" /></p>

      <p>Translation itself does not throw exceptions. If there is any problem it will return the origin value which is the english translation.</p>

      <p>Any related to "resource consuming"... when an exception is raised there is a real and unexpected problem in the code or behaviour. So resources are no problem in this case. And this also does not take much resources because there will be several translations, one for each component...</p>

      <p>I have also the opinion that the majority of developers can read english. But it would improve usability and it would reduce the problem of misunderstandings. Also some developers tend to show the user exceptions and here we have the real benefit.</p>

      <p>This would also add the benefit for developers that they could rename exception... an example exception like "password 'xxx' has to be 3 characters" could be renamed to "minimum passwordlength is 3".</p>

      1. Mar 03, 2008

        <p>This way you would encourage the developers that show exceptions to their end users to continue that very bad habit, which is absolutely not desirable.<br />
        Also, it goes against the 80/20 rule imho. 80% of the developers don't show the exception to their end-users and know enough english to know what it says.</p>

        1. Mar 03, 2008

          <p>No, this is not the truth.</p>

          <p>If a developer does not show exception to the user he would not have any differences before or after the change.</p>

          <p>But when a developer, for example, wants to log the exception to a logfile he could do this in a defined language. I don't think that this is a problematic behaviour for developers or even not desired.</p>

          <p>I thought we want to integrate innovative features like this. This is not meant that all developers must show exceptions to their users... if he does this without this proposal it's also a bad habit.</p>

          <p>Myself doesn't think that this collidates with the 80/20 rule. If he does he does also without this proposal. And only because noone supports such a feature for now why should we not tend to be innovative ? <ac:emoticon ac:name="wink" /></p>

          <p>If I would have done my code only 80/20 I would not have done any of my classes... because 80% of all developers are not using I18N <ac:emoticon ac:name="smile" /> For me this is no reason why we should not support it.</p>

          <p>So anyone will have eighter pro or con meaning of this proposal but you can not say that this will force developers to show exceptions to end-users.</p>

          1. Mar 03, 2008

            <p>For the record, I never said this proposal would force developers to show exceptions to the end-user, but merely encourage the developers that are already doing this to continue doing so.<br />
            As for the log-file, I guess it's a valid use case. Still, keep in mind that exceptions are called exceptions because they are, well... exceptions. Things that in normal operations should not even occur. In that light you could argue that the additional overhead an potential problems don't weigh up against the potential benefits, because in the ideal scenario the exceptions wouldn't get thrown in the first place.<br />
            Perhaps we won't agree on the translation issue, but that doesn't take away the fact that I would love to see those exception codes implemented <ac:emoticon ac:name="wink" /></p>

            1. Mar 03, 2008

              <blockquote>
              <p>For the record, I never said this proposal would force developers to show exceptions to the end-user, but merely encourage the developers that are already doing this to continue doing so.<br />
              As for the log-file, I guess it's a valid use case. Still, keep in mind that exceptions are called exceptions because they are, well... exceptions. Things that in normal operations should not even occur. In that light you could argue that the additional overhead an potential problems don't weigh up against the potential benefits, because in the ideal scenario the exceptions wouldn't get thrown in the first place.</p></blockquote>

              <p>Using this argument, the additional overhead should have no impact on the decision to translate exception messages or not, since they are, after all, exceptions. <ac:emoticon ac:name="wink" /></p>

              <p>I guess I wouldn't be opposed to a static method to manually turn off translation in exceptions if you're worried about performance. Something like <code>Zend_Exception::translateExceptions(false)</code>.</p>

          2. Mar 03, 2008

            <p>An alternate solution could be to have the translation files for the exceptions and allow the developer to translate them in ErrorController::errorAction(). Something like the following (example code warning <ac:emoticon ac:name="wink" />)</p>

            <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
            public function errorAction()
            {
            $translator = Zend_Registry::get('translator');

            $errors = $this->_getParam('error_handler');

            $this->view->exceptionMessage = $translator->translate($errors->exception->getCode());

            switch ($errors->type)

            Unknown macro: { // etc... }

            }
            ]]></ac:plain-text-body></ac:macro>

            <p>This could even be shaped into an action helper. </p>

        2. Jun 13, 2008

          <p>Well, the main proposal is to use exception codes. This is important in and of itself for handling different types of exceptions. Can we agree on that?</p>

          <p>Next point. You say,</p>

          <blockquote><p>80% of the developers don't show the exception to their end-users and know enough english to know what it says.</p></blockquote>

          <p>That may be true. I'm not sure. But being able to remember function names and being able to decipher exception messages are two very different things. Have you considered that we aren't hearing from the developers who don't speak English because they aren't on the English-only mailing list?</p>

          <p>There's a reason PHP 6 has native Unicode support. Here's a quote from Andrei Zmievski from Linux.com (<a class="external-link" href="http://www.linux.com/articles/60386):">http://www.linux.com/articles/60386):</a></p>

          <blockquote><p>[T]hose programmers fortunate enough to be comfortable in English, which tends to be the dominant language of computing, often see little reason to care about Unicode. "One of the things I notice," Zmievski says, "is that when I give my talk in countries outside the US, I get a full room. When I talk in the US? I get maybe a dozen."</p></blockquote>

          <p>Why is that? Well, certainly it's for the presentation side of things. But I think it's also because of this:</p>

          <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
          <?php
          class ?
          {
          public $?;
          public $?;
          public $???;

          function ?????()

          Unknown macro: { $?? = (time() - $this->???) / (365.2422 * 86400); return floor($??); }

          }

          $? = new ?();
          $?->??? = strtotime('1978-12-22 09:15');
          print '' . $?->?() . '??';
          ]]></ac:plain-text-body></ac:macro>

          <p>Edit: This example used to work. It was in Japanese.</p>

          <p>In any event, I think translation should happen somewhere. Not every developer speaks fluent English and I think it's reasonable to assume that having the ability to get a clearer understanding of the problem in your native language is very helpful. Now, you could go to a website for every exception and get the translated message, and that would work okay... but if you're logging messages, as Thomas says, that could make debugging very tedious.</p>

          <p>Look, you shouldn't display exceptions directly to users. If you're already doing that, you're going to do it regardless of localization. You can't force developers to use good practices.</p>

  14. May 22, 2008

    <p>This proposal is ready for review since October 2007, last community comment March 2008... and it's one of the proposals which can only be integrated into a major release.</p>

    <p>As we are slowly heading towards ZF2.0 it would be great if we can have a response from the Dev-Team for this proposal. I think we should now be able to decide if it's acceptable or not.</p>

    <p>And it would be great to get a Zend Liason after all the time...</p>

  15. May 24, 2008

    <p>I've spent about half-hour reading all the comments, and what I would like to say is thatI like this proposal and I agree with most of the comments made by you, both positive and negative ones.</p>

    <p>I would like to have this feature implemented because it can diminish the work done by the programmer, for instance for the log files that the application's administrator. Imagine a scenario where the administrator has a log that contains not only has registred the exception message in his language, but also the code that can be a precious reference because he can visit the ZF manual for a comprehensive description of the exception (translated in each language).</p>

    <p>I used to use exception message to inform the user that the application has encountered an error (not showing them just to the programmer), so I would be glad of having translatable exception messages.</p>

    <p>I also see the point of Bryce Lohr, he's right, this practice could lead to write more code for handling exception, and thus coupling the application code to the framework.
    <br class="atl-forced-newline" /></p>

  16. Jun 22, 2008

    <p>There are some misspells, so here is a little patch:</p>
    <ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
    19c19
    < protected $_locale = 'en';

    > protected static $_locale = 'en';
    43c43
    < self::_locale = $locale->toString();

    > self::$_locale = $locale->toString();
    47c47
    < self::_locale = $locale;

    > self::$_locale = $locale;
    ]]></ac:plain-text-body></ac:macro>

  17. Jun 24, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Comments</ac:parameter><ac:rich-text-body>
    <p>The proposal is extremely important for the ZF.</p>

    <p>It's clear, that exceptions should provide exception codes, but other things (like translation mechanism, mapping codes to components, ...) still have to be discussed in details.<br />
    We can't guarantee it can be finished before ZF 1.6 because of proposal importance and our workload.</p>

    <p>So it's moved back to the Ready for Review section to be available for discussions and improvements.</p></ac:rich-text-body></ac:macro>

    <p>Some my personal ideas:</p>
    <ul>
    <li>Use four bytes for the exception code instead of three bytes (since it's stored in integer wich has at least four bytes for all PHP implementations).</li>
    <li>Remove automatic message translation mechanism and make it optional and configurable using several static configuration methods added to Zend_Exception class and by overriding __toString magic method of Zend_Exception class (so optional translation mechanism will be involved only at text rendering time.</li>
    <li>Add into SVN repository global exceptions desccription list. So it may be versioned, merged and used to global exceptions description list documentation page (and, probably, for translations). This process should be described in the proposal.</li>
    <li>Add necessary chapter to the Coding Standard documentation section.</li>
    </ul>

    <p>Some my expirience:<br />
    Exception messages are not intended to describe anything to end-user, but they put user to absolute frustration if it uses non-native language. The reaction is "program has crashed absolutely". But if it has message in native language for end-user, than he/she can write it down and send to the support team.</p>

    1. Jul 20, 2008

      <p>Alex,</p>

      <p>As reply to your request:</p>

      <p>1.) I changed from 3 bytes to 4 bytes as wished. But I would still keep using hex values and not integers. I know they are internally stored as int so there is no neg about this, only a broader range.</p>

      <p>2.) There is no automatic translation... I don't quite know what you mean here. We have a default getMessage() method which does no translation and we have a getTranslatedMessage() which returns translated exceptions. Also the classes are only loaded when they are needed and not by default as mentioned by you. Maybe you can write what exactly you see problematic here ?</p>

      <p>3.) We must have a exception description list. This was also clear before. But we can not add anything to SVN as long as this proposal is not accepted. <ac:emoticon ac:name="smile" /></p>

      <p>4.) When this proposal is accepted we will also have to add description to the manual and also to the coding standard (which itself actually is also being reworked).</p>

      <p>Greetings<br />
      Thomas</p>

      1. Oct 13, 2008

        <p>Thomas has addressed the issues raised by Alexander, and in light of the fact that there has been no feedback from Alexander or anyone else, I'm moving this back to Ready for Recommendation.</p>

        1. Oct 13, 2008

          <p>I thought that I've moved it one or two weeks ago after a discussion on the dev-list.<br />
          Somehow it was not stored and I did not recognise it. <ac:emoticon ac:name="sad" /></p>

          <p>As small feature enhancement of this proposal which I would propose additionally:</p>

          <p>1.) We should/could add a way to use getMessage() also with translation when this is wished.<br />
          Pro would be that you would not have to change getMessages() to getTranslatedMessages() in your code and could simply get translation when setting this on the class.<br />
          A static property "TRANSLATE_MESSAGES" would fit perfect and be false per default. On true getMessages() would work like getTranslationMessages()</p>

          <p>2.) We have support for application wide locales. Also this code, as part of I18N, should use it when available. So you can not set a locale and will still get the wished translation.</p>

          1. Oct 23, 2008

            <p>Good ideas. I added a static translateMessages() method. You can add support for application-wide locales, since you know best how they work. <ac:emoticon ac:name="smile" /></p>

  18. Nov 06, 2008

    <ac:macro ac:name="note"><ac:parameter ac:name="title">Zend Official Response</ac:parameter><ac:rich-text-body>

    <p>This proposal is moved to Archived.</p>

    <p>After a long discassion we decided to move it into archived because of following reasons:</p>
    <ul>
    <li>It's not really clear which problems exception codes should solve, which can't be solved using standard exceptions mechanisms - exception types (exception classes and subclusses) and availability of full stack trace.</li>
    <li>Proposal needs to change exceptions throwing for whole framework. In the same time all proposed things may be used at component level if necessary.</li>
    <li>It's large enough work to change already created code, create full ZF exceptions list and maintain it in future.</li>
    </ul>

    <p>On the other hand exceptions translation functionality could be good idea, which may be separated into another proposal (e.g. to be used per-component basis using something like Zend_Exception_Translatable).</p>
    </ac:rich-text-body></ac:macro>