3

I am trying to work out how to interpret PHP's include construct, e.g. whether it is textual inclusion, when it is evaluated etc. As usual, the documentation is rather informal and vague.

Based on experimentation, it seems to be syntactic sugar. Specifically, the construct

include 'Baz.php'

is an expression which can be replaced with

eval('?>' . file_get_contents('Baz.php',  FILE_USE_INCLUDE_PATH))

Is this correct? Is this substitution true in the general case, or just in my tests?

Edit: as bwoebi notes, this is not generally true since the evaluated code does not have the same __DIR__ and __FILE__ magic constants. If there were some way to set them, we could model that too.

Edit 2: this question is a duplicate of this one: Equivalent of include using eval. However, all the answers there appear to omit bwoebi's point about the file path context.

1
  • 1
    No, with __DIR__ and __FILE__ you're out of luck. (I doubt that even runkit would work for these compile time constants) Commented May 15, 2014 at 15:03

2 Answers 2

2

Yes, that should be generally true.

The only differences are:

  • file context (it's now eval()'ed code, not code from that file)
  • relative paths: when you include files in other directories and they use theirselves relative paths, the file it points to might now not be found anymore
  • file_get_contents() is not affected by allow_url_include ini setting (though allow_url_fopen affect both)
Sign up to request clarification or add additional context in comments.

4 Comments

@jameshfisher to circumvent that one, you actually could just use chdir() before eval() here. (and reset it later)
I'm not sure that works; the __FILE__ and __DIR__ constants seem to stay the same?
__FILE__ and __DIR__ will match the file and directory of the included/required file. Also, relative paths only work if you have put . (shorthand for current directoy) in your include_path. Its usually not safe to rely on it being set as such.
@jameshfisher Just asked a bit around, but there is no way to override compile time constants. Impossible.
0

Other things to note are:

  • This will break PHP Opcode caching, as the file contents are read into memory as text, and then parsed/evaluated, producing a significant hit on performance if you are not expecting it. As mentioned in this question.
  • Parse errors in the code will not be fatal to the rest of the script, which has the side-effect of allowing the script execution to continue, even though logic that is expected to have happen may not have. (This may be true of other types of errors as well).
  • Error reporting will not resolve to the correct file/line, and therefore, debugging will become difficult.
  • This will not support the _once construct, which allows including/requiring files strictly once. This means duplicate class/function declarations will be fatal and/or behave unexpectedly.

I am certain there are other considerations that make this inadvisable as well. Without knowing your desired functionality or the reason you need to do this, giving you a helpful answer is difficult.

The best part of utilizing eval is the recovery from errors (if you could call this a "best" thing). If that is the benefit you are trying to take advantage of, however, this kind of is your only option.... Unfortunately...

2 Comments

error reporting only will contain eval()'ed code (as I noted in my answer), but the line is still correct. The _once construct you usually can emulate in a function. For everything else I agree.
The line of the eval statement, but will the line on which the error occurred in the eval'd be correct? Emulation is great, but why emulate all the functionality of the Standard Library function when you can just use it it's self? Emulating all of the checks and procedures of the function is possible, but not native, and thus very inefficient. As a learning exercise, I can see that, but otherwise, impractical.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.