A story about @include_once()


Once upon a time… we had this in our SimpleFilebackend:

return (file_exists($pathAndFilename) ? require_once($pathAndFilename) : FALSE);

Then we figured that using file_exists() is slow, so we changed it to this (see https://review.typo3.org/18873):

return @include_once($pathAndFilename);

That was changed again (in https://review.typo3.org/19848) to:

try {
return include_once($pathAndFilename);
} catch (\Exception $e) {
return FALSE;
}

So much for an introduction.

Currently we have test errors (see TYPO3-Neos-Commit job) because our ClassLoader tries to include a (potentially existing) proxy class using that requireOnce() method of ours. What happens if that class doesn't exist? Usually our exception handling kicks in (notices are transformed to exception), but in case of (recent) PHPUnit, this is not in effect.

So I created https://review.typo3.org/34314 and immediately someone pointed out we had removed the @ in the past. But why?

Robert Lemke wrote in the commit message back then:

This change removes the shut-up operator again from include_once() calls in the ClassLoader and SimpleFileBackend in order to provide meaningful error messages to the developer if class files or cache entries were not found.

The problem is, this is misleading. If files are not found, the effect is exactly the same, FALSE is returned, so that the autoloader chain can continue. This is exactly the intended behavior. The actual problem are errors in existing files…

So, assume you include a file with include_once():

  1. If the file does exist and all is fine, there is (obviously) no difference
  2. If the file does not exist, a notice is emitted and FALSE is returned
  3. If the file exists and returns a syntax error, PHP dies with a fatal error

Using the shut-up-operator suppresses the notice in the second case, as expected. The problem is the third case: The @ suppresses the fatal error and you end up without any meaningful information! So that is the reason we had issues with the shut-up-operator.


Comments

  1. Gravatar

    i feel, like we run through this course already at least 3-4 times regarding the ClassLoader, somehow this sneaky @ seems to crawl back in somewhere because it promises to behave and be quicker than alternatives. But time and time again it just tramples your trust with dirty spiked shoes and laughs at you. i've tried very hard to find a way get some errors from behind the @ curtain, but there was **no way** to get that (as of php 5.4 afaik).

    Maybe we should print some glaring red stickers we can all put on our laptops/screens to remind us, to NEVER EVER USE @ in conjunction with require/include.

    Cheers
    Marc

Leave a reply

Karsten Dambekalns

Creative Code Engineer

Contact / Impressum