sebastian/global-state
sebastian/global-state snapshots and restores PHP global state (globals, superglobals, ini settings, etc.), extracted from PHPUnit as a standalone component. Useful for test isolation and detecting side effects by capturing state before and after code runs.
Install as a dev dependency:
composer require --dev sebastian/global-state
First use case: Isolate tests modifying global state (e.g., $_ENV, $_SERVER, or static properties). Initialize in setUp():
use SebastianBergmann\GlobalState\Snapshot;
public function setUp(): void
{
$this->snapshot = Snapshot::snapshot();
}
Restore in tearDown():
public function tearDown(): void
{
$this->snapshot->restore();
}
Where to look first:
Snapshot::snapshot() for capturing state.Snapshot::snapshotSuperGlobalArray() for selective superglobal handling.Use snapshots to reset global state between tests, especially for:
$_GET, $_POST, $_ENV (avoid $_SESSION/$_COOKIE by default).Snapshot::snapshot(['staticProperties' => [App\Class::class]]).Snapshot::snapshot(['iniSettings' => ['error_reporting']]).Example: Selective snapshot for $_ENV
public function testEnvironmentVariables()
{
$snapshot = Snapshot::snapshot(['superGlobals' => ['$_ENV']]);
$_ENV['TEST_VAR'] = 'value';
$this->assertEquals('value', $_ENV['TEST_VAR']);
$snapshot->restore(); // $_ENV['TEST_VAR'] is unset
}
Leverage in:
PHPUnit\Framework\TestCase for legacy projects.$_SERVER).Example: Artisan Command Testing
public function testCommandModifiesGlobals()
{
$snapshot = Snapshot::snapshot(['superGlobals' => ['$_SERVER']]);
$this->artisan('command:test')->assertExitCode(0);
$snapshot->restore(); // Reset $_SERVER after command
}
['globals' => ['$_ENV']]).beforeEach in Pest).PHP Version Lock-In:
^8.0 for Laravel’s PHP 8.0–8.2 support:
"sebastian/global-state": "^8.0"
Superglobal Quirks:
$_SESSION/$_COOKIE are not snapshotted by default (risk of race conditions).snapshotSuperGlobalArray() only if you control session storage (e.g., in-memory for tests).Static Properties:
$obj->dynamic = 'x') are ignored.ReflectionClass to verify coverage.Performance Spikes:
$GLOBALS or complex objects slow snapshots.Snapshot::snapshot(['globals' => []]) to exclude unnecessary state.$snapshot->restore();
$this->assertNull($_ENV['TEST_VAR'] ?? null);
Xdebug to trace unexpected global modifications.Custom State Providers:
Implement SebastianBergmann\GlobalState\StateProviderInterface to snapshot non-standard state (e.g., Laravel’s app container):
class AppStateProvider implements StateProviderInterface
{
public function getState(): array { return ['app' => app()->bindings()]; }
public function restoreState(array $state): void { /* ... */ }
}
PHPUnit Listeners:
Hook into testStarted/testFinished to auto-manage snapshots:
use SebastianBergmann\GlobalState\Snapshot;
class GlobalStateListener implements TestListener
{
public function testStarted(Test $test): void
{
$test->snapshot = Snapshot::snapshot();
}
public function testFinished(Test $test): void
{
$test->snapshot->restore();
}
}
Config, Cache).beforeEach/afterEach for snapshot management:
beforeEach(function () {
$this->snapshot = Snapshot::snapshot(['superGlobals' => ['$_ENV']]);
});
afterEach(function () {
$this->snapshot->restore();
});
How can I help you explore Laravel packages today?