<p>I'm kind of interested in getting some feedback about this technique I picked up from somewhere.</p>

<p>I use this when a function can either succeed or fail, but you'd like to get more information about why it failed. A standard way to do this same thing would be with exception handling, but I often find it a bit over the top for this sort of thing, plus PHP4 does not offer this.</p>

<p>Basically the technique involves returning true for success, and <em>something</em> which <em>equates</em> to false for failure. Here's an example to show what I mean:</p>

<pre><code>define ('DUPLICATE_USERNAME', false);
define ('DATABASE_ERROR', 0);
define ('INSUFFICIENT_DETAILS', 0.0);
define ('OK', true);

function createUser($username) {
    // create the user and return the appropriate constant from the above
}
</code></pre>

<p>The beauty of this is that in your calling code, if you don't care WHY the user creation failed, you can write simple and readable code:</p>

<pre><code>if (createUser('fred')) {
    // yay, it worked!
} else {
    // aww, it didn't work.
}
</code></pre>

<p>If you particularly want to check why it didn't work (for logging, display to the user, or do whatever), use identity comparison with ===</p>

<pre><code>$status = createUser('fred');
if ($status) {
    // yay, it worked!
} else if ($status === DUPLICATE_USERNAME) {
    // tell the user about it and get them to try again.
} else {
    // aww, it didn't work. log it and show a generic error message? whatever.
}
</code></pre>

<p>The way I see it, the benefits of this are that it is a normal expectation that a successful execution of a function like that would return true, and failure return false.</p>

<p>The downside is that you can only have <code>7 "error" return values: false, 0, 0.0, "0", null, "", and (object) null.</code> If you forget to use identity checking you could get your program flow all wrong. Someone else has told me that using constants like an <code>enum</code> where they all equate to false is <code>"ick"</code>.</p>

<hr>

<p>So, to restate the question: how acceptable is a practise like this? Would you recommend a different way to achieve the same thing? </p>

[{'answer_id': 72589, 'author': 'Chris Broadfoot', 'author_id': 3947, 'author_profile': 'https://Stackoverflow.com/users/3947', 'pm_score': 2, 'selected': False, 'text': "<p>As long as it's documented and contracted, and not too WTFy, then there shouldn't be a problem.</p>\n\n<p>Then again, I would recommend using exceptions for something like this. It makes more sense. If you can use PHP5, then that would be the way to go. Otherwise you don't have much choice.</p>\n"}, {'answer_id': 72634, 'author': 'mmaibaum', 'author_id': 12213, 'author_profile': 'https://Stackoverflow.com/users/12213', 'pm_score': 2, 'selected': False, 'text': "<p>A more common approach I have seen when exceptions aren't available is to store the error type in a 'last_error' variable somewhere and then when a failure happens (ie it returns false) look up the error. </p>\n\n<p>Another approach is to use the venerable unix tool approach numbered error codes - return 0 for success and any integer (that maps to some error) for the various error conditions. </p>\n\n<p>Most of these suffer in comparison to exceptions when I've seen them used however.</p>\n\n<p>Just to respond to Andrew's comment - \nI agree that the last_error should not be a global and perhaps the 'somewhere' in my answer was a little vague - other people have suggested better places already so I won't bother to repeat them</p>\n"}, {'answer_id': 72656, 'author': 'Lars Mæhlum', 'author_id': 960, 'author_profile': 'https://Stackoverflow.com/users/960', 'pm_score': 2, 'selected': False, 'text': '<p>Often you will return 0 to indicate success, and 1, 2, 3, etc. to indicate different failures. Your way of doing it is kind of hackish, because you can only have so many errors, and this kind of coding <em>will</em> bite you sooner or later.</p>\n\n<p>I like defining a struct/object that includes a Boolean to indicate success, and an error message or other value indicate what kind of error occurred. You can also include other fields to indicate what kind of action was executed.  </p>\n\n<p>This makes logging very easy, since you can then just pass the status-struct into the logger, and it will then insert the appropriate log entry.</p>\n'}, {'answer_id': 72661, 'author': 'Argelbargel', 'author_id': 2992, 'author_profile': 'https://Stackoverflow.com/users/2992', 'pm_score': -1, 'selected': False, 'text': '<p>In my opinion, you should use this technique only if failure is a "normal part of operation" of your method / function. For example, it\'s as probable that a call suceeds as that it fails. If failure is a exceptional event, then you should use exception handling so your program can terminate as early and gracefully as possible.</p>\n\n<p>As for your use of different "false" values, I\'d better return an instance of a custom "Result"-class with an proper error code. Something like:</p>\n\n<pre><code>class Result\n{\n    var $_result;\n    var $_errormsg;\n\n    function Result($res, $error)\n    {\n       $this-&gt;_result = $res;\n       $ths-&gt;_errorMsg = $error\n    }\n\n    function getResult()\n    {\n       return $this-&gt;_result;\n    }\n\n    function isError()\n    {\n       return ! ((boolean) $this-&gt;_result);\n    }\n\n    function getErrorMessage()\n    {\n       return $this-&gt;_errorMsg;\n    }\n</code></pre>\n'}, {'answer_id': 72665, 'author': 'Jonathan Adelson', 'author_id': 8092, 'author_profile': 'https://Stackoverflow.com/users/8092', 'pm_score': 0, 'selected': False, 'text': "<p>Ick.</p>\n\n<p>In Unix pre-exception this is done with errno. You return 0 for success or -1 for failure, then you have a value you can retrieve with an integer error code to get the actual error. This works in all cases, because you don't have a (realistic) limit to the number of error codes. INT_MAX is certainly more than 7, and you don't have to worry about the type (errno).</p>\n\n<p>I vote against the solution proposed in the question.</p>\n"}, {'answer_id': 72673, 'author': 'ima', 'author_id': 5733, 'author_profile': 'https://Stackoverflow.com/users/5733', 'pm_score': -1, 'selected': False, 'text': '<p>Look at COM HRESULT for a correct way to do it.</p>\n\n<p>But exceptions are generally better.</p>\n\n<p>Update: the correct way is: define as many error values as you want, not only "false" ones. Use function succeeded() to check if function succeeded.</p>\n\n<pre><code>if (succeeded(result = MyFunction()))\n  ...\nelse\n  ...\n</code></pre>\n'}, {'answer_id': 72730, 'author': 'Jeremy Privett', 'author_id': 560, 'author_profile': 'https://Stackoverflow.com/users/560', 'pm_score': 5, 'selected': True, 'text': "<p>I agree with the others who have stated that this is a little on the WTFy side. If it's clearly documented functionality, then it's less of an issue, but I think it'd be safer to take an alternate route of returning 0 for success and integers for error codes. If you don't like that idea or the idea of a global last error variable, consider redefining your function as:</p>\n\n<pre><code>function createUser($username, &amp;$error)\n</code></pre>\n\n<p>Then you can use:</p>\n\n<pre><code>if (createUser('fred', $error)) {\n    echo 'success';\n}\nelse {\n    echo $error;\n}\n</code></pre>\n\n<p>Inside createUser, just populate $error with any error you encounter and it'll be accessible outside of the function scope due to the reference.</p>\n"}, {'answer_id': 72838, 'author': 'ljorquera', 'author_id': 9132, 'author_profile': 'https://Stackoverflow.com/users/9132', 'pm_score': 0, 'selected': False, 'text': "<p>If you really want to do this kind of thing, you should have different values for each error, and check for success. Something like</p>\n\n<pre><code>define ('OK', 0);\ndefine ('DUPLICATE_USERNAME', 1);\ndefine ('DATABASE_ERROR', 2);\ndefine ('INSUFFICIENT_DETAILS', 3);\n</code></pre>\n\n<p>And check:</p>\n\n<pre><code>if (createUser('fred') == OK) {\n    //OK\n\n}\nelse {\n    //Fail\n}\n</code></pre>\n"}, {'answer_id': 72926, 'author': 'rami', 'author_id': 9629, 'author_profile': 'https://Stackoverflow.com/users/9629', 'pm_score': 0, 'selected': False, 'text': "<p>It does make sense that a successful execution returns true. Handling generic errors will be much easier:</p>\n\n<pre><code>if (!createUser($username)) {\n// the dingo ate my user.\n// deal with it.\n}\n</code></pre>\n\n<p>But it doesn't make sense at all to associate meaning with different types of false. False should mean one thing and one thing only, regardless of the type or how the programming language treats it. If you're going to define error status constants anyway, better stick with switch/case</p>\n\n<pre><code>define(DUPLICATE_USERNAME, 4)\ndefine(USERNAME_NOT_ALPHANUM, 8)\n\nswitch ($status) {\ncase DUPLICATE_USERNAME:\n  // sorry hun, there's someone else\n  break;\ncase USERNAME_NOT_ALPHANUM:\n  break;\ndefault:\n  // yay, it worked\n}\n</code></pre>\n\n<p>Also with this technique, you'll be able to bitwise AND and OR status messages, so you can return status messages that carry more than one meaning like <code>DUPLICATE_USERNAME &amp; USERNAME_NOT_ALPHANUM</code> and treat it appropriately. This isn't always a good idea, it depends on how you use it.</p>\n"}, {'answer_id': 73049, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<blockquote>\n  <p>how acceptable is a practice like this?</p>\n</blockquote>\n\n<p>I\'d say it\'s unacceptable.</p>\n\n<ol>\n<li>Requires the === operator, which is very dangerous. If the user used ==, it leads to a very hard to find bug.</li>\n<li>Using "0" and "" to denote false may change in future PHP versions. Plus in a lot of other languages "0" and "" does not evaluate to false which leads to great confusion</li>\n</ol>\n\n<p>Using getLastError() type of global function is probably the best practice in PHP because it <em>ties in well with the language</em>, since PHP is still mostly a procedural langauge. I think another problem with the approach you just gave is that very few other systems work like that. The programmer has to learn this way of error checking which is the source of errors. It\'s best to make things work like how most people expect.</p>\n\n<pre><code>if ( makeClient() )\n{ // happy scenario goes here }\n\nelse\n{\n    // error handling all goes inside this block\n    switch ( getMakeClientError() )\n    { case: // .. }\n}\n</code></pre>\n'}, {'answer_id': 73100, 'author': 'inxilpro', 'author_id': 12549, 'author_profile': 'https://Stackoverflow.com/users/12549', 'pm_score': 1, 'selected': False, 'text': '<p>When exceptions aren\'t available, I\'d use the <a href="http://en.wikipedia.org/wiki/PEAR" rel="nofollow noreferrer">PEAR</a> model and provide isError() functionality in all your classes.</p>\n'}, {'answer_id': 73455, 'author': 'Markowitch', 'author_id': 11964, 'author_profile': 'https://Stackoverflow.com/users/11964', 'pm_score': 0, 'selected': False, 'text': "<p>I like the way COM can handle both exception and non-exception capable callers. The example below show how a HRESULT is tested and an exception is thrown in case of failure. (usually autogenerated in tli files)</p>\n\n<pre><code>inline _bstr_t IMyClass::GetName ( ) {\n    BSTR _result;\n    HRESULT _hr = get_name(&amp;_result);\n    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));\n    return _bstr_t(_result, false);\n}\n</code></pre>\n\n<p>Using return values will affect readability by having error handling scattered and worst case, the return values are never checked by the code. That's why I prefer exception when a contract is breached.</p>\n"}, {'answer_id': 73589, 'author': 'Aquarion', 'author_id': 12696, 'author_profile': 'https://Stackoverflow.com/users/12696', 'pm_score': 0, 'selected': False, 'text': '<p>Other ways include exceptions:</p>\n\n<pre><code>throw new Validation_Exception_SQLDuplicate("There\'s someone else, hun");),\n</code></pre>\n\n<p>returning structures,</p>\n\n<pre><code>return new Result($status, $stuff);\nif ($result-&gt;status == 0) {\n    $stuff = $result-&gt;data;\n}\nelse {\n    die(\'Oh hell\');\n}\n</code></pre>\n\n<p>I would hate to be the person who came after you for using the code pattern you suggested originally.</p>\n\n<p>And I mean "Came after you" as in "followed you in employment and had to maintain the code" rather than "came after you" "with a wedgiematic", though both are options.</p>\n'}, {'answer_id': 86759, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 1, 'selected': False, 'text': '<p>Reinventing the wheel here. Using squares.</p>\n\n<p>OK, you don\'t have exceptions in PHP 4. Welcome in the year 1982, take a look at C.</p>\n\n<p>You can have error codes. Consider negative values, they seem more intuitive, so you would just have to check if (createUser() > 0).</p>\n\n<p>You can have an error log if you want, with error messages (or just arbitrary error codes) pushed onto an array, dealt with elegance afterwards.</p>\n\n<p>But PHP is a loosely typed language for a reason, and throwing error codes that have different types but evaluate to the same "false" is something that shouldn\'t be done. </p>\n\n<p>What happens when you run out of built-in types?</p>\n\n<p>What happens when you get a new coder and have to explain how this thing works? Say, in 6 months, you won\'t remember.</p>\n\n<p>Is PHP === operator fast enough to get through it? Is it faster than error codes? or any other method?</p>\n\n<p>Just drop it.</p>\n'}]
['https://Stackoverflow.com/questions/72564', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/9021/']