0

I have a script that checks if a port is accessible on an IP address. So whether I choose to do that with file_get_contents or with fsockopen, the concept stays the same, which is that I have to call either of those functions in order to get my result. E.g., there is no equivalent to file_exists which would "guarantee" that calling file_get_contents would not generate an error when calling a URL.

What bugs me in this kind of a scenario, is that an error is a completely acceptable part in the flow of the program, and therefore shouldn't be treated as other ("actual") errors across my application. Because what I usually have running is a custom error handler, for any occasion where something unexpected would fail, which writes the error message in a log file, and then displays a big 404-like error page. Which means that in this case, I have to do a restore_error_handler, in order to be able to do @file_get_contents without a massive error screen appearing, in order to check if the result of it is false.

So currently that's how it works, and the output is correct, but the approach seems wrong. What I am wondering is, is there a prettier way of solving this type of a scenario? One that wouldn't require me to unset something that that is application-wide, and that would resemble a try-catch approach more.

3
  • 3
    IMHO you should never use @, you should capture errors and handle them gracefully for the user while logging them for your perusal. Commented Sep 8, 2015 at 12:05
  • I don't know if you've actually read the question, Jay, but there is nothing to log in this case, because there is nothing wrong. Trying to fetch a URL for the purpose of finding out whether a port is open, and receiving a negative result, is not an error in the application. Commented Sep 8, 2015 at 12:10
  • I was answer the question you posed in your title. As for your scenario you should be catching these "issues" and handling them in a way that makes sense to you. Commented Sep 8, 2015 at 12:23

2 Answers 2

3

I'll start with the very best option, even though it doesn't actually exist yet.

When PHP 7 is released (currently at beta 3, so final release should be some time in the next couple of months), it will feature a completely re-written error handling system.

The new PHP 7 error handler turns all the old PHP errors into a new type of exception. This means that you can simply use try ... catch to handle them, just like other exceptions. This will simplify PHP error handling enormously, and for me is one of the major selling points of moving up to PHP 7 as soon as possible after it's released.

However, it isn't released yet, and you may not be able to / willing to upgrade to it immediately anyway, so here are the other options:

  1. Switch to the alternative OO classes.
    Many PHP functions have object oriented alternatives which throw exceptions rather than old-style errors. For example, you specified file_get_contents() in your question; these can be replaced with calls to the SplFileObject class. fsockopen() is often used for making http calls, so maybe swap that code out for the Guzzle library. And so on. There's usually a way of doing things that avoids having to rely on the old functions at all.

  2. If you really do need to rely on the old functions, and you really can't find a way to check for potential errors before calling them, then you need to consider using the old error handling function set_error_handler(). This function allows you to specify a function which will be called when an error occurs. Once in the error handling function, you can do what is necessary to handle it and either return (in which case the original code will contine at the next line) or die gracefully if the error can't be recovered from.

Ultimately, though, you're absolutely right -- PHP errors are a bit of a dogs breakfast, and really not easy to work with. The @ operator stinks, but occasionally there really isn't any alternative to it. I haven't found myself using one in a long time now, so you really shouldn't need it, but I do concede that it may be necessary from time to time simply because PHP doesn't offer anything better.

That will change with PHP 7; the error handling is one of many things which are being drastically improved. I'm looking forward to its release.

Sign up to request clarification or add additional context in comments.

Comments

1

What I am wondering is, is there a prettier way of solving this type of a scenario? One that wouldn't require me to unset something that that is application-wide, and that would resemble a try-catch approach more.

Whether this is "prettier" is opinion-based, but you can convert all errors to exception in your custom error handler, which allows you to actually catch them:

set_error_handler(function($num, $msg, $file, $line)
{
    // Convert to exceptions
    throw new ErrorException($msg, 0, $num, $file, $line);
});
set_exception_handler(function($e)
{
    // Print or log to file
    echo get_class($e).': '.$e->getMessage().' ['.$e->getFile().':'.$e->getLine().']';
});

try
{
    // Will be caught
    echo array();
}
catch(ErrorException $e) {}

// Will not be caught
echo array();

[ Demo ]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.