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
include
ing 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 byallow_url_include
ini setting (thoughallow_url_fopen
affect both)
Related Topics
Mysql: Get Total in Last Row of MySQL Result
Working with Japanese Filenames in PHP 5.3 and Windows Vista
Nl2Br() Equivalent in JavaScript
Class App\Http\Controllers\Usercontroller Does Not Exist
Mongodb Aggregate Query Using PHP Driver
Codeigniter Command Line Error - PHP Fatal Error: Class 'Ci_Controller' Not Found
Merge Two Png Images with PHP Gd Library
Why Is Turning Magic_Quotes_Gpc on Considered a Bad Practice
Mod_Rewrite to Remove .PHP But Still Serve the .PHP File
Set Cart Item Price from a Hidden Input Field Custom Price in Woocommerce 3
Destination Path for Move_Uploaded_File in PHP
Strip_Tags() Function Blacklist Rather Than Whitelist
PHP - Override Existing Function
PHP Get Height and Width in PDF File Proprieties
Defining a Namespace for Laravel 8 Routes
What Is the Rfc Compliant and Working Regular Expression to Check If a String Is a Valid Url