Is there any way to include a PHP file, and be able to read what values global variables and/or class static properties would have in that file’s scope, without polluting those same global variables and static class properties in the calling scope?
Say I have example.php
:
$latestExample = null;
class Example {
public $name;
public static examples = [];
public function __construct($name) {
$this->name = $name;
self::$examples[] = $this;
$latestExample = $this;
}
}
If I use include('example.php')
, the $latestExample
and Example::$examples
will be filled by this file—I don’t want that. Instead, I want to do something where everything from this file is restricted to some other scope, and my own global variables and static class properties are untouched.
Important details about the file I’m “including”
require_once
.$GLOBALS
, not necessarily just by writing variables in the root scope. That seems to nix this answer.The explanation here is that I have an extensive, extremely complicated, custom-written system that leverages global variables and static class properties extensively. Implicitly, the global space is treated as its own “object” that the page is representing. This was a questionable choice when I first made it, years and years ago, but it’s mostly served me fairly well because each page really is devoted to all the details and such of a particular subject. All the variables and objects I was creating were things owned by that subject.
Except now, of course, I have cases where a subject can have sub-subjects, and I want to re-use everything I have for individual subjects for the sub-subjects because they have gotten sufficiently complicated. Problem is, running the scripts to create the sub-subjects will pollute the global variables and static class properties for the primary subject, making the scripts think all of those properties are properties of the main subject, too.
I have tried to look into “sandbox” options for PHP, but most of what I can find is either defunct, or an online tool or environment. This isn’t about security; I don’t need a separate process or anything like that. It’s plausible that some of what I have seen could do the job, but since they’re not geared for that I can’t find guidance on how to use them for that.
For the curious, the system produces a character sheet for a Dungeons & Dragons “v.3.5 revised edition” character. Each page is the sheet for a given character, so the global variables and static class properties are supposed to be stats, abilities, and features of that character. Now I just want to include the stats and properties of another character—a minion—within the same page as the main character. In the past I had just manually created such sections, but now I have a minion who is fully as complex as a full character, and I want to re-use everything I have for creating the sheet of a character for the sake of this minion’s section on the main character’s sheet.
My solution here was to create a version of my “sub-subject” code that, instead of echo
’ing HTML, echo
’ed a JSON of the variables I was interested in with json_encode
.
Then the other file used json_decode(`php sub-subject-json.php`);
. The backtick operator executes a shell command, in this case, php
itself called with the file I want to look at.
So, for example, where previously I might have had
minion.php
<?php
$name = 'Steve';
$attack = 3;
$damage = '1d6+3';
?><!DOCTYPE html>
<html>
<head><title><?php echo $name; ?></title></head>
<body>
<h1><?php echo $name; ?></h1>
<p><?php echo formatBonus($attack) . " $damage"; ?>
</body>
</html>
Now I have
minion-core.php
<?php
$name = 'Steve';
$attack = 3;
$damage = '1d6+3';
?>
minion.php
<?php require_once('minion-core.php'); ?><!DOCTYPE html>
<html>
<head><title><?php echo $name; ?></title></head>
<body>
<h1><?php echo $name; ?></h1>
<p><?php echo formatBonus($attack) . " $damage"; ?>
</body>
</html>
minion-json.php
<?php
require_once('minion-core.php');
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'name' => $name,
'attack' => $attack,
'damage' => $damage,
]);
?>
And then my main file can include
leader.php
$steve = json_decode(`php minion-json.php`);
This is a nasty, ugly hack. But it does work, and it works without refactoring everything I’ve written.