Php: Equivalent of Include Using Eval

PHP: Equivalent of include using eval

After some more research I found out what was wrong myself. The problem is in the fact that <?php is a "short opening tag" and so will only work if short_open_tag is set to 1 (in php.ini or something to the same effect). The correct full tag is <?php, which has a space after the second p.

As such the proper equivalent of the include is:

eval('?>' . file_get_contents('external.php') . '<?php ');

Alternatively, you can leave the opening tag out all together (as noted in the comments below):

eval('?>' . file_get_contents('external.php'));

My original solution was to add a semicolon, which also works, but looks a lot less clean if you ask me:

eval('?>' . file_get_contents('external.php') . '<?php;');

PHP - Is there a way to include a string as a file?

If you want the string to be parsed as PHP code, just like the contents of a file loaded with include(), then the function you need is eval().

Note that, unlike code loaded by include(), code executed by eval() automatically starts in PHP mode, so you don't need to (and shouldn't!) prefix it with <?php. If you want to emulate the behavior of include() exactly, you can prefix the string to be eval()ed with ?> to leave PHP mode:

$string = file_get_contents( 'somefile.php' );
eval( '?>' . $string );

Also note that eval() is a very dangerous function to play with! While in this specific case it shouldn't be any more risky than include() itself is, using eval() on any string that might even possibly contain unsanitized (or insufficiently sanitized) user input is extremely dangerous, and may be exploited by attackers to execute malicious code on your system and thereby gain control of it.

Is eval() functionally the same as include in PHP, given the following example?

No. Call stack would be changed (error messages, magic constant __FILE__). Relative includes in evaled code could be broken. Two new variables $codeToModify, $codeToEval would appear in evaled code scope. Evaled code would not be cached. Parse error inside evaled code does not interrupt whole script. Eval could be disabled with Suhosin.

Using Eval to include remote php file

This:

  • Has all the security downsides of includeing remote files
  • Is massively inefficient due to all the extra HTTP requests
  • Means that a new release of a library gets deployed without being tested against the rest of the code in an application
  • Adds an extra point of failure for the application

Don't do this. It is a terrible idea.

Installation of dependencies should be a feature of your install script, not the application itself.

include vs eval for php framework

The "problem" you are trying to solve is generally considered a good thing: if the code has to live in a file somewhere, then you need a naming convention for such files in order to organise the project; and since you also need a naming convention for namespaces and classes, aligning the two actually saves effort, because you don't need to keep track of both conventions.

PHP also includes a feature which gives an even stronger advantage to this, in the form of autoloading. This allows you to write a function which, whenever you mention a class that hasn't been defined yet, will be called with that class name; by aligning your filenames to class names, it can then find and load that class. This is tremendously useful as your project grows, because it means you never need to add require or include to files, or work out the exact tree of dependencies required for a particular area of your code. The major frameworks have collaborated on a standardised directory layout to take advantage of this, called PSR-4.

While it can be annoying having to create large numbers of directories and separate files, and tempting to put many small classes into one file, this doesn't scale well, and if one of those small classes later grows, you'll regret it not having its own file, with its own version history, etc.

If you don't name your files after the class they contain, you will need to either manually manage a complex set of require/include lines tracking the right order to define everything in, or have an autoloader function with a long list mapping class names to filenames. Either sounds like a lot of work for no gain to me.

If your files are going to be named after the class anyway, then an autoloader would still work, but the only thing you are gaining is that you don't need to type the words class Cart at the top of the file. On the other hand, you will need to create a rather unusual function for including these files, involving a rather inefficient use of eval(). Things like OpCache and HHVM will find it much harder to cache and optimise code loaded this way, and any tool performing static analysis will be completely defeated as the code in the file will not be valid (e.g. PHPCodeSniffer for reporting on coding standards, PHPDocumentor, or any editor or IDE providing function lists and syntax parsing features).

Finally, it is often remarked that code is read much more often than it is written. The step you are saving happens, for the vast majority of classes, exactly once - when the class is first created. Renaming or copying a class is generally a very rare occurrence, and if you're renaming a large number of files, it's fairly easy to make a script to automate the task. On the other hand, you are introducing several things which make reading your code harder. As well as confounding static analysis (and thus automated documentation), you will have to explain this idiosyncratic scheme to new developers working on the project, so effectively increase your training costs. There is also the problem that, once this scales beyond a single directory, you will have to look at the full directory path of a file to see what class it actually defines; I frequently end up with several files open with the same name (e.g. search_handler.php) and the fact that I (and my editor) can look at the top of the file for the full class declaration is essential for keeping track of which is which.

PHP Eval alternative to include a file

After few tests I finally managed to find a solution which doesn't require versionning anymore.

$reflectionClass = new \ReflectionClass($this);
$lastUpdatedTimeOnStart = filemtime($reflectionClass->getFileName());

while (true) {
clearstatcache();
$reflectionClass = new \ReflectionClass($this);
$lastUpdatedTime = filemtime($reflectionClass->getFileName());
if ($lastUpdatedTime != $lastUpdatedTimeOnStart) {
// An update has been made, exit
} else {
// worker hasn't been modified since running
}
}

Whenever the file will be updated, the worker will automatically exit
Thanks to @Rudie who pointed me into the right direction.

PHP include semantics

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)


Related Topics



Leave a reply



Submit