Reputation: 869
There's some PHP code assigned to one variable ($phpCode) that may contain a function called runjustthis() or/and any other php code.
I'm looking for a possibility to run just that function runjustthis() with eval().
In other words, how do I extract (with a regex?) the function runjustthis() from the string $phpCode and then call eval() on the extracted string?
Pseudo code:
$phpCode = "
function runjustthis() {
// some code here...
}
// maybe some more code here...
// Don't execute that:
$something = '123';
somethingElse();
";
$runjustthis = extractFunction("runjustthis", $phpCode);
eval($runjustthis);
Upvotes: 3
Views: 214
Reputation: 28499
The cleanest approach would be to use a PHP parser written in PHP to parse the text, then extract the function from the syntax tree created by the parser and execute it.
One example of a php parser writtein in php is https://github.com/nikic/PHP-Parser
Sample code:
<?php
$phpCode = <<<'CODE'
<?php
// Bla Bla
$else = 'something';
function donRunThis() {
echo "Zonk";
}
function runjustthis() {
// some code here...
echo 42;
}
class X {
}
// maybe some more code here...
// Don't execute that:
$something = '123';
echo "Zonk";
somethingElse();
?>
CODE;
// Function to extract the code from a function with the given name from the given php code.
function extractFunction($name, $phpCode)
{
// Create parser and parse php code
$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7);
$ast = $parser->parse($phpCode);
// Find first function with the given name
$nodeFinder = new PhpParser\NodeFinder;
$func = $nodeFinder->findFirst($ast, function(PhpParser\Node $node) use ($name)
{
// Node must be a function
if($node instanceof PhpParser\Node\Stmt\Function_)
{
// and have the correct name
if($node->name->toString() === $name)
{
return true;
}
}
return false;
});
// If function was found
if($func)
{
// Use pretty printer to get text representation of the statements in the function
$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
$funcCode = $prettyPrinter->prettyPrint($func->stmts);
return $funcCode;
}
}
$runjustthis = extractFunction("runjustthis", $phpCode);
eval($runjustthis);
?>
Try it out at PHP Sandbox:
https://phpsandbox.io/n/super-base-mgkn-nbiyn
Upvotes: 0
Reputation: 3608
You do not need anything else. as the doc says:
The code will be executed in the scope of the code calling eval(). Thus any variables defined or changed in the eval() call will remain visible after it terminates.
So you just need:
<?php
$phpCode = "
function runjustthis() {
return 'Hi';
}
function runjustthis2(){
return 'working?';
}
";
eval($phpCode);
echo runjustthis(). PHP_EOL;
echo runjustthis2();
Output
Hi
working?
But if you insists on getting only the function you want(part of $phpCode
), so you can do this:
<?php
$phpCode = "
function runjustthis() {
return 'Hi';
}
function runjustthis2(){
return 'working?';
}
";
function extractFunction($functionName, $code){
$pattern = "/function (?<functionName>$functionName+)\(\)(\s+)?\{[^\}]+\}/m";
preg_match_all($pattern, $code, $matches);
return($matches[0][0]);
}
$runjustthis = extractFunction("runjustthis", $phpCode);
eval($runjustthis);
echo runjustthis();
This would only execute the runjustthis()
function not other codes which wrote in $phpCode
, so if we try runjustthis2()
it will get this error:
PHP Fatal error: Uncaught Error: Call to undefined function runjustthis2() in your/file/directory/file_name.php
Upvotes: 2