php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67860 Throw an "acceptable" exception
Submitted: 2014-08-19 01:13 UTC Modified: 2017-08-05 04:56 UTC
Votes:2
Avg. Score:1.0 ± 0.0
Reproduced:0 of 2 (0.0%)
From: david dot proweb at gmail dot com Assigned:
Status: Suspended Package: *General Issues
PHP Version: Irrelevant OS: Irrelevant
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2014-08-19 01:13 UTC] david dot proweb at gmail dot com
Description:
------------
Imagine that you do ($a / $b), but $b is zero.
So you will receives "Warning: Division by zero.".

You can avoid that by doing @($a / $b), something like that.

But imagine if PHP can thrown an exception that not need be captured.
It is: you can, optionally, capture that, but if not, will only thrown a notice, instead of warning.

// Supposing that it is the PHP division constructor:
function php_div($a, $b) {
    if($b === 0) {
        throw casual new Exception("Division by zero.");
    }

    return $a / $b;
}

// So if I do:
5 / 0; // Notice: Division by zero.

// But I can do:
try { 5 / 0; }
catch(Exception $e) { ... } // Avoid notice.

// Or even:
@(5 / 0); // Avoid casual Exception.

--

User can throw casual exceptions too.
For instance:

function name_fix($name) {
    ...
    if(name_uncommon($name)) {
        throw casual new Exception("This name is uncommon.");
    }
    ...
    return $name_fixed;
}

echo name_fix("David"); // David
echo name_fix("Hakuna Matata"); // Hakuna Matata + Notice

// When you capture that, statement will be blocked.
try { echo name_fix("Hakuna Matata"); }
catch(Exception $e) { echo "The Hakuna Matata is so uncommon."; }
// -> The Hakuna Matata is so uncommon. (not echo name, not notice)

--

Exception need a new property like `boolean $isCasual` ($e->isCasual()).

--

Note: apply it to "division by zero" is only to examplify my feature request.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-08-19 01:49 UTC] requinix@php.net
-Package: PHP Language Specification +Package: *General Issues
 [2014-08-19 01:49 UTC] requinix@php.net
If you don't want to deal with exceptions then don't use them in your code.
 [2014-08-19 01:56 UTC] david dot proweb at gmail dot com
Actually it would make errors in a casual exception, so that I could capture it in a more reliable manner.

$variable = [1, 2, 3];
echo $variable;

// Notice: Array to string conversion.

How I can capture that? (In this case, I could avoid it by checking if the variable is compatible, but it is only an example.)

With the feature, I could do:

try { echo $variable; }
catch(Exception $e) {
    if(strpos($e->getMessage(), "Array to string conversion")) {
        echo "Check option `user_type`, it accept only string.";
    }
}
 [2014-08-19 19:34 UTC] salathe@php.net
The described behaviour can already be done.

<?php

set_error_handler(function ($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    echo $variable;
} catch (Exception $e) {
    echo "D'oh! " . $e->getMessage();
}

?>

Outputs:

    D'oh! Undefined variable: variable

Alternatively, you could always write sensible code that doesn't raise notices.
 [2014-08-19 19:52 UTC] david dot proweb at gmail dot com
Your example can handle that, fine.
But imagine that:

I'm developing a framework, and it have a method that return current URL, but check if it is secure too (I don't know what user will do with that), but, even if not, the execution will works normally (user need check that, or I need to develop a method that check it "manually").

With this option, I can thrown a casual exception, but not fatal. User can check that or just ignore. It'll depends if user really want to capture this exception. Supposing that he is just logging user URL, for instance.

    $log->url = Framework::getCurrentUrl();
    $log->save();

In this case, I not need capture the exception, I just not need to check security on URL.

Now, if user need to avoid bad URLs, I can do that:

    try { $user->url = Framework::getCurrentUrl(); }
    catch(BadURL_Exception $e) { 
        echo "Sorry, your URL is insecure.";
        return false;
    }

To uncaptured exception, PHP can show a notice error, that can be hidden on error_reporting() or INI;
 [2014-08-20 21:52 UTC] phpmpan at mpan dot pl
Considering that exceptions are meant to alter program flow, the proposed "causal exception" is not really an exception. It's a camouflaged call to a global function that later returns to the caller. Just as any normal function would.

You can achieve the same effect already with code like that:
------------------------------------------------------------
final class Warnings {
    
    public static function consume($callback = null) {
        if (!self::$consuming) {
            if ($callback == null) {
                $callback = function() {};
            }
            if (is_string($callback)) {
                $callbackString = $callback;
                $callback = function($errno, $errstr) use ($callbackString) {
                    eval($callbackString);
                };
            }
            set_error_handler($callback, E_WARNING);
        }
    }
    
    public static function pass() {
        if (self::$consuming) {
            restore_error_handler();
        }
    }
    
    private static $consuming = false;
}

function doSomething() {
    echo 1 / 0;
}

try {
    Warnings::consume();
    doSomething();
} finally {
    Warnings::pass();
}

try {
    Warnings::consume(function($_1, $errstr) {echo "WARNING: $errstr\n";});
    doSomething();
} finally {
    Warnings::pass();
}
 [2017-08-05 04:56 UTC] stas@php.net
-Status: Open +Status: Suspended
 [2017-08-05 04:56 UTC] stas@php.net
Thank you for your interest in PHP and for submitting a feature request. Please be aware that due to the magnitude of change this request requires, it would be necessary to discuss it on PHP Internals list (internals@lists.php.net) as an RFC. Please read the guide about creating RFCs here:
https://wiki.php.net/rfc/howto
If you haven't had experience with writing RFCs before, it is advised to seek guidance on the Internals list (http://php.net/mailing-lists.php) and/or solicit help from one of the experienced developers. 

Please to not consider this comment as a negative view on the merits of your proposal - every proposal which requires changes of certain magnitude, even the very successful and widely supported ones, must be done through the RFC process. This helps make the process predictable, transparent and accessible to all developers.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC