- What is sebastian/global-state used for?
- It is a stand-alone component, factored out of PHPUnit, that takes a snapshot of PHP global state and can restore it later. The snapshot covers superglobals such as $_ENV, $_SERVER, $_SESSION, $_GET and $_POST, plus user-defined constants and static properties of declared classes. Teams use it to isolate tests from each other and to detect unintended global side effects. It is a test-isolation primitive, not a runtime feature for Laravel applications.
- How do I install sebastian/global-state in a Laravel project?
- Run composer require --dev sebastian/global-state so the package stays on the development autoload path. In most Laravel projects it is already present transitively through phpunit/phpunit, so check composer show sebastian/global-state before adding it explicitly. Installation is trivial; the real decision is whether you want to own that dependency and its upgrade tickets.
- Do I still need sebastian/global-state if Laravel already isolates my tests?
- Usually not. Laravel covers the common leakage categories with RefreshDatabase, a fresh application instance per test, container rebinding, Facade::clearResolvedInstances(), and the fake() helpers. Reach for this package only when you have a measured flake rate caused by global or static state that Laravel's isolation does not touch, such as legacy superglobal code, static caches, or singleton services. Adopting it pre-emptively against a hypothetical problem is usually wasted effort.
- Which PHP versions does sebastian/global-state support?
- Support windows move in lockstep with PHPUnit majors, so the exact PHP range depends on the version Composer resolves for you. As a rough guide, the 9.x line drops PHP 8.3 support, 8.x targets PHP 8.0 through 8.2, and 7.x spans PHP 8.1 through 8.3. Because the package usually arrives transitively, its support window can silently become a constraint on your Laravel and PHP upgrade train.
- How do I take a snapshot and restore global state in a test?
- Instantiate SebastianBergmann\GlobalState\Snapshot at the start of the test, then pass it to SebastianBergmann\GlobalState\Restorer and call restore() when you are done. In practice you hide both behind a small trait or base-class hook so engineers never call the package directly. Keep the wrapper short and use try/finally rather than relying on tearDown ordering, which breaks easily when another team inserts a base class between you and the framework.
- Does sebastian/global-state capture all global state?
- No. Capture is reflection-based, so it sees declared properties and user-defined constants only. Dynamic properties and internal object state escape the snapshot, which means a test can pass while state still leaks. That silent under-capture is worse than a visible failure, so do not treat a green suite as proof that leakage is gone.
- Is sebastian/global-state safe to use in production code?
- It should never be on the production autoload path. Restoring $_ENV, $_SERVER or $_SESSION outside a test teardown is a stability and security concern, not a convenience. Add it as a dev dependency and contain it behind a test-only trait so application code cannot reach it. If any team is calling it outside tests, treat that as a stop-work signal.
- Does sebastian/global-state work with parallel testing such as Paratest?
- A full snapshot restore mutates process-wide state, so restore semantics under parallel runners need explicit validation rather than assumption. If you run Paratest or any worker loop that needs deterministic resets between iterations, write a test that proves the behaviour you expect before depending on it. Treat concurrency as a correctness question, not a cleanup nicety.
- Should I add sebastian/global-state as a direct dependency or rely on PHPUnit's transitive install?
- Leaving the transitive dependency alone is the default and usually the right call. Declaring it directly converts a free transitive pin into an explicitly owned one, which means your team now fields the upgrade tickets when the PHP support window shifts. Adopt it explicitly only with a measured problem, a contained wrapper, and a named owner for test infrastructure.
- What are the alternatives to sebastian/global-state for isolating Laravel tests?
- Start with the framework: RefreshDatabase, per-test application instances, container rebinding, Facade::clearResolvedInstances(), and the fake() helpers cover most leakage in feature tests. For process-level resets you can also run tests in separate processes or reset specific globals in a base TestCase. The package earns its place mainly inside a shared base TestCase, an internal test-harness package, or a non-PHPUnit runner.