Ever thought “Gee, it would be nice if I could store some PHP in a database and execute it at will?”
Well you’re in luck my friend, PHP was thinking of you when they created the eval
function.
The syntax for eval
is very simple:
eval ( string $code_str );
Unfortunately, the output of eval does not work like you might expect it to. You can’t, for instance, do this:
$string_awesome = eval(string $code_str)
The string will remain empty and eval will function as though it weren’t at the right hand side of an assignment. This is because of the way eval works. Eval is not intended to deal solely with code that outputs something to the screen. It simply executes the provided code inline with the rest of the code. It can share variables, functions, and anything else with the main body. So the following would work just fine:
$number = 1;
eval ("$number = $number + 1");
echo $number;
The preceding would output 2. Notice that it was necessary to escape each dollar sign. Eval requires a pure PHP string. Any normal PHP operations have to be escaped out, including single quotes, double quotes, dollar signs, etc or it will not work properly.
Since eval is not primarily concerned with output, it doesn’t return any. In order to capture the output to a string you have to do something called output buffering. Output buffering simply captures any output of desired PHP statements and allows you to manipulate it before display (or even choose not to display at all). It has many applications beyond the scope of eval. Output buffering uses a variety of functions. We will demonstrate most of them in the following examples.
Back to our original example, let’s assume we have a string of PHP code which we are going to execute via an eval statement and we would like any output to be captured to a string. To do this, we’d simply run:
ob_start();
eval("echo "This is some really fine output."");
$this_string = ob_get_contents();
ob_end_clean();
Simple enough right? With ob_start
, we…start output buffering. We use ob_get_contents
to capture the collected output to a string, and we use ob_end_clean
to exit the whole thing nicely. The value of $this_string
will be “This is some really fine output.”
But what if we had two eval statements to run and wanted two different strings? Well, we could just run the above code twice, but PHP provides a function called ob_get_clean that simplifies the task. The resulting code looks like:
ob_start();
eval("echo "This is some really fine output."");
$this_first_string = ob_get_clean();
eval("echo "This is some more fine output."");
$this_second_string = ob_get_contents();
ob_end_clean();
Using ob_get_clean
for the first part of the capture scrubs the output buffer and allows it to collect more output without restarting the whole process. This results in cleaner code (and I expect faster executions).
There is one more trick in the output buffering bag that may prove useful. If you want to capture the output of an eval to a string but also display it as if it were simply being executed inline, you can simply use one of the flush functions. Flushing sends the output buffer along its merry way, as if it were never captured. It also cleans the output buffer so it is important to run one of the ob_get* functions before we use flush. PHP even provides variations of the core functions using flush:
ob_start();
eval("echo "Some awesome output. "");
$this_string = ob_get_contents();
ob_end_flush();
The preceding code will output the output buffer and also store it in $this_string. You can also use ob_get_flush
or ob_flush
to further simplify this depending on your particular application.
Paul Ingraham says
Thank you for this clear explanation, kind stranger. It was a great relief to me this afternoon to find this page!
Sebastian says
Your code samples are coming up as hex strings: the first one’s displaying as “deee70b3a62ff9ddd4faa45401478de8000”, for instance. Perhaps your code samples are being executed?
Mahendran says
i need a clear coding.it is not understandable..can you give the understandable coding..
Sebastian says
How bizarre – they’re now displaying as normal code. Maybe finding this site through Google had something to do with it…
Lowelhal says
Couldn’t you just add a return statement to the string?
Lowelhal says
Couldn’t you just add a return statement to the string?
Guilhermo Luna says
Thank you very much!
With your code I file the result of a whole page into a var. Like this:
ob_start();eval(“if($show_news==1) { require_once(“news.php”);}”);$news= ob_get_clean();ob_start();
Guilhermo Luna says
Thank you very much!
With your code I file the result of a whole page into a var. Like this:
ob_start();eval(“if($show_news==1) { require_once(“news.php”);}”);$news= ob_get_clean();ob_start();
Eviiiiiiiiiiiiiiiiiiiil says
Very Nice in a way that i can say excellent PHP ! and you too!
I can now do some EVIL stuff ……..
Eviiiiiiiiiiiiiiiiiiiil says
Very Nice in a way that i can say excellent PHP ! and you too!
I can now do some EVIL stuff ……..
Sergii Savchenko says
Nice artcile) helped a lot, thanks!
Sergii Savchenko says
Nice artcile) helped a lot, thanks!
Fabrizio Sabato says
Very good article.
I changed something in order to make it work with “include” files like this:
ob_start();
eval(‘?>’ . file_get_contents( $fileToRequire, TRUE ) . ‘<?
php ');
$string = ob_get_contents();
ob_end_clean();
Thanks a lot for your help 😉
Blake says
Thank you. Thank you. Thank you. THANK YOU. Exactly what I was looking for!