4

Possible Duplicate:
Reference - What does this symbol mean in PHP?

I'm making a web application that uses URL queries to access different parts of the application. I was looking for a solution to make an invalid query like index.php?page=dashboarrrd display an error 404 message instead of a PHP error.

After some searching, I found that I could use something like the following to do the job:

if(!@include($fileName)){
    @include("pageData/404.php");
}

And that makes sense, but I don't know why that works. I mean, what the heck does the @ before the include mean? I totally understand include $filename; but I need an explanation for @include ($fileName)

Community
  • 1
  • 1
Titus
  • 4,277
  • 5
  • 27
  • 40
  • @Gordon, thank you for bringing that to my attention. It's a fantastic reference, and definitely deserves bookmarking :) In all honesty, though, I couldn't find anything about my question (searching for characters is problematic for various reasons), and those that I did find didn't satisfy me or help me at all. Therefore, I thought it appropriate to start a new question. And I'm glad I did, too: within a half hour I not only got wonderful explanations of the `@` operator but I also got great suggestions on how to get around that for my particular circumstance! :) – Titus Mar 17 '11 at 23:35

7 Answers7

10

This is the @ Error Control Operator (quoting) :

When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.


In normal conditions, if include cannot load the file you've passed as a parameter, it'll emit a warning.

Prepending the @ operator to include will prevent that warning from being emited -- and, so, from being displayed / logged.


So, the following portion of code :

include 'does-not-exist.php';

Will get you the following warnings :

Warning: include(does-not-exist.php) [function.include]: failed to open stream: No such file or directory
Warning: include() [function.include]: Failed opening 'does-not-exist.php' for inclusion

While this line :

@include 'does-not-exist.php';

Will get you not warning.


And, as a sidenote, for information : Five reasons why the shut-op operator (@) should be avoided

Pascal MARTIN
  • 374,560
  • 73
  • 631
  • 650
  • Generally i frown on error supression... if there is a chance it might not exist on a regular basis then use `file_exists` and/or `is_readable` first. If there is no good reason for the file not to exist then you need to be notified of the error. Just my opinion though... – prodigitalson Mar 17 '11 at 22:05
  • @ operator has nothing to do with *displaying* – Your Common Sense Mar 17 '11 at 22:07
  • @Col I've edited my answer to be more precise on that point ; thanks for your comment :-) – Pascal MARTIN Mar 17 '11 at 22:09
  • Three of the linked "Five reasons..." are microoptimization arguments. The other two are unobjective generalizations or baloney. – mario Mar 17 '11 at 22:16
  • The first reason *(debugging hell)* by itself is far more than enough to avoid @ as much as possible -- I've been handed over a couple of buggy / badly-coded projects with @ operators everywhere, and it's been a nightmare... – Pascal MARTIN Mar 17 '11 at 22:19
  • @Pascal MARTIN Thank you for your very detailed answer. I was torn apart between your answer and @Col's answer, as both were **exceptional**. However, I settled on @Col's answer because of a suggested method for me to implement the 404 message (using `is_readable`). – Titus Mar 17 '11 at 23:24
10

the code you really need is

$fileName = "pagedata/".basename($_GET['page']).".php";

if(is_readable($fileName)) {
    include($fileName);
} else {
    include("pagedata/404.php");
}

and @ has absolutely nothing to do here

@ is one of biggest delusions coming from lack of experience.
Ones who using it do expect only one kind of error, while in fact there can be many more. And to gag ALL possible messages to suppress only one of them is definitely like to throw out the child along with the bath.

There is a fundamental problem that makes such misunderstanding so widespread:

Most PHP users cannot distinguish three sides of error control:

  1. error handling
  2. error reporting
  3. user notification.

Most of time in sake of [3] people mess with (1) and (2). While each of them require separate treatment:

  1. your program should raise no intentional errors. No error should be part of program logic. All errors that ever raised should be only unexpected ones.
    if you expect some error, you have to handle it. Not gag with @, but gracefully handle. is_readable() in my code exactly for that.
  2. error reporting is for the programmer and should be always at max. So, error logging should be enabled on a live site and a programmer have to check all errors occurred. And of course he would be interested in such errors, thus @ will do only harm here.
  3. User-level error messages should be different from system ones. Your 404.php is a good example of such user-friendly behavior. As for the system error messages, a user shouldn't be able to see them at all. Just turn display_errors off and see - there is no use for the @ again!
Your Common Sense
  • 152,517
  • 33
  • 193
  • 313
  • +1 REALLY like your tip about `is_readable`. I tested this out in my code and it works great! As for suppressing errors, I was horrified when you said `@` suppressed errors. I would never (in my right mind) knowingly do that!!! :D – Titus Mar 17 '11 at 23:19
3

The @ suppresses errors. This is generally discouraged, as when developing you want to see errors.

Errors are easy to suppress when moving to a production environment with the display_errors setting to off. So yea, in most cases, there really is no need for the error to be suppressed.


EDIT

As an extra tidbit to "improve" that, what I used to do when dynamically including a file, is have an array which acts as a "white list" of valid requests. This does not "have" to be an array, just what I chose to do an example with.

$whiteList = array('filename1', 'index', 'home', 'about');

if (in_array($filename, $whiteList)) {
    include($filename); 
}else {
    include('page/404.php');
}

This would do a few things, 1 make you not need the error suppressor. Two, it would make it a bit more securer, as without this, you would need to do a basename call to filter the text to prevent certain type of include injections etc. (Not knowing if you did this already, just extra information).

So yea, you may want analyze / look at other ways to achieve this and above is just one method :)

Jimithus
  • 18,016
  • 5
  • 45
  • 63
1

The use of "@" simply suppresses the error that would normally result from (in this instance) a missing file. Whilst generally its use is a very bad idea, there are some rare exceptions, such as the code snippet you provide above.

For more information, see the Error Control Operators section of the PHP manual.

Additionally, you might find the existing Reference - What does this symbol mean in PHP? question worthy of a quick scan.

Community
  • 1
  • 1
John Parker
  • 52,372
  • 11
  • 124
  • 125
  • how come this code snippet become an exception? here goes the same very bad idea as well – Your Common Sense Mar 17 '11 at 22:08
  • @Col Good point. Whilst it's fractionally faster than having to do a file_exists, etc. first it's probably still a bad idea. I'll update my answer accordingly. – John Parker Mar 17 '11 at 22:09
0

The @ in php suppresses all error output. For instance, if you had error reporting for warnings, an @ in front of a function that generated a warning would not display the warning text.

include is an example of such a construct. If the included file is not found, it will display a warning saying so. The @ is not necessary in the code at all, it is just there so that the user will not see warnings.

However, it is better to use apache (or php if you prefer) to change ini for displaying errors on the development site and not displaying them on the production site. That would make the @ symbol useless.

A better question is why you need to do this 404 include. Why are you including a file for display? Why not have apache handle 404 redirects on its own? Why wouldn't the file exist in the first place?

Explosion Pills
  • 176,581
  • 46
  • 285
  • 363
0

@ suppresses error messages. The parentheses are optional in include, but whoever wrote that snippet included them.

kindall
  • 158,047
  • 31
  • 244
  • 289
0

@include() is the opposite of require(). The first will silently ignore an (optional and missing) include script, while the second will throw an error and halt the script when the (critical) dependency is missing.

In this instance it is only senseful within the if(). The second should preferrably not have an error suppression, as it doesn't mask any seriously security-relevant error message.

mario
  • 138,064
  • 18
  • 223
  • 277