I have a static method named ServerResponse that basically shows a message whether on success or fail. I just want to know the proper way to actually display the message and exit the script.
Should I implement my method like this:
public static function ServerResponse($e,$m){
print(json_encode([$e,$m]));
exit;
}
//Sample use:
if(this happens){
myclass::ServerResponse($x,$y);
}
or like this:
public static function ServerResponse($e,$m){
return json_encode([$e,$m]);
}
//Sample use:
if(this happens){
print(myclass::ServerResponse($x,$y));
exit;
}
Which one is proper and better... and why?
is there any difference between them? (on execution time).
"Don't be hard on me I am not an expert (just yet)..."
For better debugging, it's advised to always make a function or method return a value. So your 2nd sample should be chosen.
exit (or die) are commonly used when the program ends with an error, giving the ability to add an exit status (as a number or a string).
I suppose there will be no significant difference about the execution time.
I don't know if this is common practice but I only use exit to debug. If your script comes to the end of execution it will exit on it's own.
If you must exit, do it in the main script, not in a function.
functions should have one task and do that task. So the function ServerResponse should send a response and not kill the script.
I'm having an issue with the following code. I'm just guessing it's a scope problem.
public function run() {
return eval('$this->config();');
// This will return null.
return $this->config();
// This will return my config array right.
}
Before anyone asks:
Not both return are 'active' when testing.
I know eval is evil, but i'm building some kind of terminal for admins to run PHP code.
Do anyone have any suggestions about this terminal thing? (My basic problem is still with the eval...)
eval is returning NULL because that is what it is suppose to do. Right from the documentation page:
eval() returns NULL unless return is called in the evaluated code, in which case the value passed to return is returned.
I'm having an issue with PHP as it keeps throwing the Exception mention in the title.
It fails on the following line:
$item->getDescription();
I understand what the error should mean ($item is null). However, $item is not null.
The scenario is as follows:
This is a script that syncs products from a supplier to a store. For that purpose, I have created my own class (SimpleProduct). This class has a getDescription() function.
The problem is that the data I'm receiving tend to have a lot of garbage, like items that haven't been filled in yet. The script should skip these items and keep on iterating across the rest of the products.
This fatal error kills the entire script.
I've already tried implementind safeguards to prevent this from happening, but it still occurs constantly. Here's the current code (some snippets removed as they arent pertinent to the currect case).
//This is part of a class that performs the sync
public function syncProduct($item) {
if(empty($item)) { return "Not a product"; }
else { var_dump($item) }
$foo = $item->getDescription();
}
When checking the var_dump result, I get an object with some values filled in. Seeing as it is of the correct type (SimpleProduct) and it is not empty/null, I would suspect this error to stop occurring, but it still does.
Also note that several product syncs have already occurred without any errors before this one pops up, so I know the code is valid. Somehow, this specific case slips past my null-checks.
Is my null-check faulty?
How can an error for a non-object be thrown when the object in question does exist?
Instead of checking whether if the variable is empty, why not check whether if it's an instance of SimpleProduct?
if ($item instanceof SimpleProduct)
{
}
http://php.net/manual/en/language.operators.type.php
Surely the object is still not available in the context of the function syncProduct.
Try to do a var_dump($item) to confirm its there and execute it within the else part of the code to ensure its not empty.
To check if $item is an object You can use is_object()
Your null check is not preventing the object to be used even if it is null contains non-objects.
Use this:
public function syncProduct($item) {
var_dump($item);
if($item InstanceOf SimpleProduct) {
$foo = $item->getDescription();
}
return "Not a product";
}
I stand corrected! I didn't notice the return statement. The other case for this to occur would be if the value from $item would be non-empty but not a product either - most likely a scalar or array because using objects as other types of objects issue a different error regarding methods not being found.
I also run into a similar problem where after running this:
$user = DB::getInstance()->action($action="SELECT * ", 'users');
Then checking whether $user is an instance of DB, I found that it wasn't. I then decided separate it as follows:
$user = DB::getInstance();
$user->action($action="SELECT * ", 'users');
After doing this and using instanceof() method it shows that it is now an instance and the fatal call to member function error disappears.
There is a way to check with a "IF" if a function fails in php?
Ex.
If (getimagesize($image) returns and error) {
echo 'Error: function dont work';
}
else
{
// do something
}
Thanks!
I 'm assuming you are interested specifically in a function like getimagesize, which does not return any error codes and makes it hard on us. But not impossible.
The documentation for getimagesize states:
If accessing the filename image is impossible, or if it isn't a valid picture, getimagesize() will generate an error of level E_WARNING. On read error, getimagesize() will generate an error of level E_NOTICE.
Therefore, you need to do two things:
Get notified of the error and act upon it somehow
Have the error not be displayed or otherwise affect the execution of your program at all (after all, your are going to be taking care of any errors with error-handling code yourself)
You can achieve the first one using set_error_handler() and restore_error_handler(). You can achieve the second with the error-control operator #.
So, the code must go something like this:
// Set our own error handler; we will restore the default one afterwards.
// Our new error handler need only handle E_WARNING and E_NOTICE, as per
// the documentation of getimagesize().
set_error_handler("my_error_handler", E_WARNING | E_NOTICE);
// No error has occured yet; it is the responsibility of my_error_handler
// to set $error_occurred to true if an error occurs.
$error_occurred = false;
// Call getimagesize; use operator # to have errors not be generated
// However, your error handler WILL STILL BE CALLED, as the documentation
// for set_error_handler() states.
$size = #getimagesize(...);
// At this point, my_error_handler will have run if an error occurred, and
// $error_occurred will be true. Before doing anything with it, restore the
// previous error handler
restore_error_handler();
if($error_occurred) {
// whatever
}
else {
// no error; $size holds information we can use
}
function my_error_handler($errno, $errstr, $file, $line) {
global $error_occurred;
// If the code is written as above, then we KNOW that an error
// here was caused by getimagesize(). We also know what error it was:
switch($errno) {
case E_WARNING: // Access to image impossible, or not a valid picture
case E_NOTICE: // Read error
}
// We could also check what $file is and maybe do something based on that,
// if this error handler is used from multiple places. However, I would not
// recommend that. If you need more functionality, just package all of this
// into a class and use the objects of that class to store more state.
$error_occurred = true;
return true; // Do not let PHP's default error handler handle this after us
}
Of course, this is not very maintainable (you have a global variable $error_occurred there, and this is not a good practice). So for a solution which not only works but is also nicely engineered, you would package all this in a class. That class would define:
A method which implements the error handler (my_error_handler in the above example). To set an object method as an error handler instead of a global function, you need to call set_error_handler with a suitable first parameter; see the documentation for callback.
A method which lets the class set the error handler, execute some code of your choice, save the "error happened while executing your code" flag, and restore the error handler. This method could e.g. take a callback provided by your calling code and an array of parameters and use call_user_func_array to execute it. If, during execution, the error handler set from #1 above is called, mark this in a variable in your object. Your method would return the return value of call_user_func_array to the calling code.
A method or variable which the calling code can use to access the result from #2 above.
So then, if that class is called ErrorWatcher, your calling code would be something like:
$watcher = new ErrorWatcher;
$size = $watcher->watch("getimagesize",
array( /* params for getimagesize here */ ));
// $size holds your result, if an error did not occur;
// check for errors and we 're done!
switch($watcher->report_last_error()) {
// error handling logic here
}
...which is nice and neat and does not mess with global variables. I hope I explained this well enough to enable you to write class ErrorWatcher yourself. :-)
Take a look at exceptions. You'll have to throw them in your function though.
Edit: By the way, if your function is not supposed to return a boolean, you can always have it return false if something goes wrong and check like:
$result = getimagesize($image);
if ($result === false)
{
//
}
Whatever the condition is on an "if" statement (what's inside the parenthesis) will return "true" or "false".
If the condition returns "true", the first statement will be executed, otherwise the second statement will get executed.
You can put this, error_reporting(E_ALL); at the very top of your script, right after your opening php tag, to see what error you get.
Hope it helps.
Maybe something like this:
<?php
error_reporting(E_ALL);
more stuff here ...
if(your condition here){
echo "condition is true, do something";
}else{
echo "condition is not true, do something else";
}
if the function or statement you run inside the "if" or "else" fails, at least you know which one was it based on the result, and the error_reporting might tell you why it failed.
I'm kind of interested in getting some feedback about this technique I picked up from somewhere.
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.
Basically the technique involves returning true for success, and something which equates to false for failure. Here's an example to show what I mean:
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
}
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:
if (createUser('fred')) {
// yay, it worked!
} else {
// aww, it didn't work.
}
If you particularly want to check why it didn't work (for logging, display to the user, or do whatever), use identity comparison with ===
$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.
}
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.
The downside is that you can only have 7 "error" return values: false, 0, 0.0, "0", null, "", and (object) null. 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 enum where they all equate to false is "ick".
So, to restate the question: how acceptable is a practise like this? Would you recommend a different way to achieve the same thing?
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:
function createUser($username, &$error)
Then you can use:
if (createUser('fred', $error)) {
echo 'success';
}
else {
echo $error;
}
Inside createUser, just populate $error with any error you encounter and it'll be accessible outside of the function scope due to the reference.
As long as it's documented and contracted, and not too WTFy, then there shouldn't be a problem.
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.
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.
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.
Most of these suffer in comparison to exceptions when I've seen them used however.
Just to respond to Andrew's comment -
I 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
how acceptable is a practice like this?
I'd say it's unacceptable.
Requires the === operator, which is very dangerous. If the user used ==, it leads to a very hard to find bug.
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
Using getLastError() type of global function is probably the best practice in PHP because it ties in well with the language, 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.
if ( makeClient() )
{ // happy scenario goes here }
else
{
// error handling all goes inside this block
switch ( getMakeClientError() )
{ case: // .. }
}
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 will bite you sooner or later.
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.
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.
Reinventing the wheel here. Using squares.
OK, you don't have exceptions in PHP 4. Welcome in the year 1982, take a look at C.
You can have error codes. Consider negative values, they seem more intuitive, so you would just have to check if (createUser() > 0).
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.
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.
What happens when you run out of built-in types?
What happens when you get a new coder and have to explain how this thing works? Say, in 6 months, you won't remember.
Is PHP === operator fast enough to get through it? Is it faster than error codes? or any other method?
Just drop it.
When exceptions aren't available, I'd use the PEAR model and provide isError() functionality in all your classes.
Ick.
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).
I vote against the solution proposed in the question.
It does make sense that a successful execution returns true. Handling generic errors will be much easier:
if (!createUser($username)) {
// the dingo ate my user.
// deal with it.
}
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
define(DUPLICATE_USERNAME, 4)
define(USERNAME_NOT_ALPHANUM, 8)
switch ($status) {
case DUPLICATE_USERNAME:
// sorry hun, there's someone else
break;
case USERNAME_NOT_ALPHANUM:
break;
default:
// yay, it worked
}
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 DUPLICATE_USERNAME & USERNAME_NOT_ALPHANUM and treat it appropriately. This isn't always a good idea, it depends on how you use it.
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)
inline _bstr_t IMyClass::GetName ( ) {
BSTR _result;
HRESULT _hr = get_name(&_result);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _bstr_t(_result, false);
}
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.
If you really want to do this kind of thing, you should have different values for each error, and check for success. Something like
define ('OK', 0);
define ('DUPLICATE_USERNAME', 1);
define ('DATABASE_ERROR', 2);
define ('INSUFFICIENT_DETAILS', 3);
And check:
if (createUser('fred') == OK) {
//OK
}
else {
//Fail
}
Other ways include exceptions:
throw new Validation_Exception_SQLDuplicate("There's someone else, hun");),
returning structures,
return new Result($status, $stuff);
if ($result->status == 0) {
$stuff = $result->data;
}
else {
die('Oh hell');
}
I would hate to be the person who came after you for using the code pattern you suggested originally.
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.
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.
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:
class Result
{
var $_result;
var $_errormsg;
function Result($res, $error)
{
$this->_result = $res;
$ths->_errorMsg = $error
}
function getResult()
{
return $this->_result;
}
function isError()
{
return ! ((boolean) $this->_result);
}
function getErrorMessage()
{
return $this->_errorMsg;
}
Look at COM HRESULT for a correct way to do it.
But exceptions are generally better.
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.
if (succeeded(result = MyFunction()))
...
else
...