PHP and exceptions. Your opinion?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Atli
    Recognized Expert Expert
    • Nov 2006
    • 5062

    #1

    PHP and exceptions. Your opinion?

    Hi.

    I'm a C# programmer by nature so I'm kind of used to using Exceptions and I'm currently working on a PHP project that I've written in a .Net style, using Exceptions ,objects and naming styles like I would in C#.

    None of the original PHP functions or objects use the Exception system. They are written to return error codes or boolean values rather then throw exceptions.
    This is obviously the 'default' way of coding PHP, and I doubt many people use the Exception system, except 'C like' coders like myself, which would create problems if someone other than myself were to use my code.

    I'm just wandering what you guys think.
    Does anybody use Exceptions other than me? Should I just give it a rest and try to follow the PHP way of doing things?

    And more importantly; is there any clear advantage/disadvantage of using Exceptions that you know of?
  • kovik
    Recognized Expert Top Contributor
    • Jun 2007
    • 1044

    #2
    No, the only reason PHP didn't use exceptions is because PHP didn't have exceptions. Though it is mostly reserved to the more experienced programmers so far (as it is new to the language), I highly recommend their use. There are no clear disadvantages to their use other than if you don't catch the exception, then you have an uncaught exception.

    However, I don't see you leaving them uncaught. ;)

    Comment

    • pbmods
      Recognized Expert Expert
      • Apr 2007
      • 5821

      #3
      I'm not a fan because they break so many rules.

      First off, when you throw an exception, your code halts, and the catch block (which might be located outside the procedure that threw the exception) gets executed. This doesn't make sense to me, because exception recovery should be handled within the context of that exception (Demeter's Law and the basic premise behind OOP).

      For example:[code=php]function addOne($file) {
      $a = file($file);
      ++$GLOBALS['files'];
      $a[] = 1;
      return $a;
      }

      $i = 'notafile';
      try {
      addOne($i);
      } catch (Exception $e) {
      --$GLOBALS['files'];
      }[/code]

      If you didn't know what addOne() did, the presence of "$GLOBALS['files']" in the catch block would be confusing.

      Secondly, exceptions interrupt program execution. A procedure might be able to recover from an exception and continue, but this is very difficult to implement with try ... catch.

      For example, this code throws an exception:[code=php]function addOne($file) {
      $a = file($file.'.ph p');
      ++$GLOBALS['files'];
      $a[] = 1;
      return $a;
      }

      $i = 'notafile';
      try {
      addOne($i);
      } catch (Exception $e) {
      --$GLOBALS['files'];
      }[/code]

      But what if (say for backwards compatibility) the file *could* be located in the parent directory instead?

      There's no way to go back into addOne() and try the other value of $i once that exception gets thrown.

      Now, you might offer that we could simply move the try ... catch inside of addOne... if you are in the habit of using a sledgehammer when a ball-peen will do (see below*).

      And thirdly, how is this:[code=php]try {
      someRiskyFuncti on();
      } catch (Exception $e) {
      .
      .
      .
      }[/code]

      any different from this:[code=php]if(! @someRiskyFunct ion()) {
      .
      .
      .
      }[/code]

      My solution to the above situation would be to do my error checking inside of the risky function so that I don't have to worry about the function throwing exceptions.

      *And in the case of addOne(), a simple is_array() check works wonders.
      Last edited by pbmods; Jul 4 '07, 02:34 AM. Reason: Added some stars to make this a real a-list post!

      Comment

      • kovik
        Recognized Expert Top Contributor
        • Jun 2007
        • 1044

        #4
        Exceptions are meant more for fatal errors than other things. Saying that this code could work EXCEPT once this function has failed, there's no coming back. :P

        Comment

        • dafodil
          Contributor
          • Jul 2007
          • 389

          #5
          Exceptions are used to track what particular errors were caused by a system...

          In php there are no exceptions but there are certain functions that can track errors...

          For example in the mysql functions of php you can track errors on db....

          But still why would you want to create it harder....

          You should not worry about that anymore because it's up to the server to track errors...

          If you really want to make your life miserable you can create your own exceptions.

          "Why re-invent the wheel?"

          Hope this helps you in your programming stand...

          Comment

          • Atli
            Recognized Expert Expert
            • Nov 2006
            • 5062

            #6
            I think exceptions are perfect for situations where an error will definitely cause problems later in the code, in which case it's execution must be stopped before other problems occur.

            Like say I were trying to query a database. If a connection to the server can not be made, then the code must be stopped before it tries to use the closed connection.
            This can be accomplished like this:
            [code=php]
            // Connect to database
            $DB = @mysql_connect( "host", "user", "pw");
            @mysql_select_d b("db", $DB);

            if(!!$DB) {
            // Execute query
            $q = "SELECT * FROM tbl";
            $r = @mysql_query($q );

            if(!!$r) {
            // Use the results
            } else {
            // Print query error
            die("Query failed: <pre>". mysql_error() ."</pre>");
            }
            } else {
            // Print connection error
            die("Connection failed: <pre>". mysql_error() ."</pre>");
            }
            [/code]
            There are obviously other ways to handle this, but most of them use the die() or echo() commands to print messages and rely on boolean checks on the retuning data from the functions, which results in nested if statements and / or long, nearly unmanageable, die() calls after function calls.

            If the functions were to throw exceptions rather than return boolean values, all these die() and mysql_error() calls as well as the if statments would be unnecessary.
            We would have one line printing our error message, no matter how many different functions we use or how many different exceptions we may catch, all without a single boolean check.
            [code=php]
            try {
            // Connect to database
            $DB = @mysql_connect( "host", "user", "pw");
            @mysql_select_d b("db", $DB);

            // Run query
            $q = "SELECT * FROM tbl";
            $r = @mysql_query($q , $DB);

            // Use the results
            }
            catch(Exception $ex) {
            // Print any exception
            echo "<b>Excepti on cought</b><pre>". $ex->getMessage() ."</pre>";
            }
            [/code]

            This looks a whole lot cleaner, don't you think?

            Only thing that bothers me is that there is no final clause.

            Comment

            • pbmods
              Recognized Expert Expert
              • Apr 2007
              • 5821

              #7
              Heya, Atli.

              To specifically tackle the MySQL connection issue, my frameworks check for a valid MySQL connection almost as soon as each script starts up and redirect to a 'routine maintenance' (or the like) page on error, while logging the error and emailing the site administrator.

              No exceptions needed.

              That's a much more User-friendly solution than echoing an error message in the middle of where the User is expecting to see output.

              I guess I can see how Exceptions might be useful in a development environment, but I don't see how they can be considered the best solution for sites that are designed to have Users.

              Comment

              • Atli
                Recognized Expert Expert
                • Nov 2006
                • 5062

                #8
                Originally posted by pbmods
                Heya, Atli.

                To specifically tackle the MySQL connection issue, my frameworks check for a valid MySQL connection almost as soon as each script starts up and redirect to a 'routine maintenance' (or the like) page on error, while logging the error and emailing the site administrator.
                That's my approach as well. I'm very object orientated so I have a Database object that is connected at the top of the script and then gets passed into each object that requires it, and is then closed at the end.
                I've even gone so far as to create a Index object, that is executed in a similar way Forms are executed in .Net

                Originally posted by pbmods
                That's a much more User-friendly solution than echoing an error message in the middle of where the User is expecting to see output.

                I guess I can see how Exceptions might be useful in a development environment, but I don't see how they can be considered the best solution for sites that are designed to have Users.
                All my scripts are entirely wrapped into a try..catch block, which redirects to a error page if an unhandled exception is cought.
                That way, if an unhandled exception is thrown I show the user a nice 'Sorry, please try again' page and log the error message and the precise line in the file that caused the exception, which makes debugging easy.

                So far, I haven't seen anything better or worse about using exceptions. It's really just a matter of how you want to design your code, what you are comfortable with.

                The only real difference I can see is that Exceptions will always cause your code to crash if they are not handled, which is easy to debug.
                The conventional boolean return values can be ignored and go unnoticed, but that can lead to a massive collapse of all code that is depending on that one failed function. That on the other hand can be a little more challenging to debug.

                Comment

                • pbmods
                  Recognized Expert Expert
                  • Apr 2007
                  • 5821

                  #9
                  Heya, Atli.

                  Interesting points.

                  Originally posted by Atli
                  I've even gone so far as to create a Index object, that is executed in a similar way Forms are executed in .Net
                  Do you have a link, or could you elaborate on this? I'm not familiar with .NET.

                  Comment

                  • kovik
                    Recognized Expert Top Contributor
                    • Jun 2007
                    • 1044

                    #10
                    Just see exceptions as an alternative to trigger_error. It's meant to give the user an idea of what went wrong rather than just saying "something went wrong."

                    Comment

                    • Atli
                      Recognized Expert Expert
                      • Nov 2006
                      • 5062

                      #11
                      Originally posted by pbmods
                      Heya, Atli.

                      Interesting points.

                      Do you have a link, or could you elaborate on this? I'm not familiar with .NET.
                      Sure, I don't have any links but I can attempt an explanation.

                      When I say Forms, I mean Windows Forms, like say the Window you browser is displayed in.

                      To create a form in .Net you simply override the Form class in the System.Windows. Forms namespace and execute it, typically in the Main method.
                      It then takes over the main thread and returns it only when the window has been disposed of. The form handles the Windows message queue, all events and all drawing of the form.

                      I implement the same idea in PHP by creating a class that does all includes and initialization in the constructor. This class is then created and initialized in the index. It then calls the Main method that creates and returns the output back to the index where it is echoed to the browser. Lastly I create a Dispose() method where I dispose of any class instances and close all database links.

                      I know this may sound a bit much but it helps to organize the code and keep it clean.

                      Comment

                      Working...