kolemp/timecop-bundle
Timecop Bundle freezes, travels, and scales time in your tests so date- and time-dependent code behaves predictably. Control the clock globally, write deterministic assertions for Carbon and DateTime, and eliminate flaky time-based failures.
Recommendation: No-go. Reject adoption as a dependency; at most, vendor the ~1–2 relevant classes under MIT terms if a specific gap is ever proven. The package's score (0.05) and dependent count (0) align with the qualitative read below.
Architecture fit — poor, and mismatched at the framework layer. Despite being evaluated as a "Laravel/PHP package," kolemp/timecop-bundle is a Symfony bundle. Its integration surface is a Bundle subclass plus a DI extension and configuration tree — all artifacts Laravel does not consume. There is no Laravel service provider, no auto-discovery entry, and no config publishing. In a Laravel app the bundle scaffolding is dead weight; only the underlying time-interception library could plausibly be reused, and that library is a separate dependency with its own dormancy risk. Layering a Symfony-kernel component into a Laravel app to reach a testing utility is inverted architecture.
Integration feasibility — low, and the use case is already covered natively. The bundle's purpose (freezing or traveling the clock in tests) is served in Laravel by first-party means: Carbon::setTestNow() on any Laravel version we would support, and travel() / travelTo() / freezeTime() helpers in the test suite since Laravel 8. Those are maintained, documented, framework-native, and require zero new dependencies. Any engineer who would reach for this package can instead write a single line. The remaining niche — freezing time() / new DateTime() outside Carbon — is exactly where the technical risk concentrates, because interception of native PHP time functions typically requires a PECL extension, namespace rewriting, or autoload trickery that we do not want in CI.
Technical risk — high and concentrated in unknowns. Last release 2018-09-18; roughly seven years without a tag. Single-maintainer project with a bus factor of one and no downstream dependents to absorb maintenance. The 2018 vintage implies a Symfony HttpKernel constraint (^3/^4 era) and PHP 7-era code, which will contend with PHP 8.1+ deprecations and Carbon 2/3 in any current Laravel release. Installing it pulls symfony/http-kernel — a component Laravel does not otherwise ship — into the dependency graph purely to satisfy a bundle base class.
Key questions to close before any further spend:
uopz/runkit, stream/namespace wrapper)? If it requires a PECL extension, the answer is a hard no for CI portability.time(), microtime(), and new DateTime() in addition to Carbon? If only Carbon, it is strictly inferior to Carbon::setTestNow().Stack fit — does not fit. Target stack is Laravel on PHP 8.x with Carbon 2/3 and PHPUnit/Pest. The package targets Symfony's kernel and bundle lifecycle. There is no composer extra.laravel block, no provider, no facade. The realistic integration is not "install the package" but "read two files and reimplement," which is a different, cheaper decision.
Migration path — none required; choose the native path. The migration is not to this package but away from any bespoke clock-mocking utility toward:
Carbon::setTestNow($when) and Carbon::setTestNow() in tearDown for the general case.$this->travelTo(), $this->travel(5)->minutes(), $this->freezeTime() in Laravel feature tests.Clock interface (PSR-20's ClockInterface is the emerging standard) rather than intercepting the runtime.That refactor is the durable fix and removes the class of problem this package exists to paper over.
Compatibility — unverified and likely broken. PHP 8.1+ deprecation exposure, Carbon major-version coupling, and a Symfony HttpKernel major-version constraint from 2018 all need a composer resolution spike to confirm. Assume it does not install cleanly against a current Laravel skeleton until proven otherwise; do not plan around it.
Sequencing.
composer require --dev in a throwaway Laravel 11 app; record resolution conflicts and whether any clock is actually intercepted beyond Carbon. This is the only spend justified.Clock abstraction to the one or two production services that call native time. Document both in the testing guide.time()/date() calls in application code so the gap never reopens.Maintenance — unacceptable as a standing dependency. An untagged-since-2018, single-maintainer, zero-dependent repository means every future PHP or Carbon bump becomes our incident, with no upstream to escalate to. We would be the de facto maintainer of code we did not write, for functionality we do not need. The one durable asset is the MIT license, which makes a small vendor-and-own fork legally clean if the spike ever justifies it.
Support — no viable escalation path. No releases, no downstream users to surface regressions, no indication of security triage. Any CVE in the transitive Symfony HttpKernel chain becomes ours to patch or pin. For a dev-only dependency the blast radius is contained to CI, but so is the value — asymmetric in the wrong direction.
Scaling — zero production impact, negative test-suite impact. This is a require-dev concern; it touches no runtime path, no request latency, no horizontal scaling story. It does, however, complicate test-suite scaling: if the interception mechanism holds process-global or static state, ParallelTesting (ParaTest) and Pest's concurrency will leak frozen clocks across workers, producing nondeterministic failures that grow with shard count. A frozen clock that silently fails to freeze is worse than no clock control at all, because tests pass against real time and rot quietly.
Failure modes to expect:
Ramp-up — near-zero cost, near-zero payoff. Any engineer productive with PHPUnit and Carbon is productive with the native helpers on day one; there is no API to learn. The package's only ramp-up cost is the negative kind — engineers must learn why a 2018 Symfony bundle is in a Laravel composer.json, and that explanation does not survive scrutiny. The correct onboarding artifact is a two-paragraph testing-standard note pointing at Carbon::setTestNow() and the Clock interface, not a dependency.
Bottom line: low score, zero dependents, dormant upstream, framework mismatch, and a first-party alternative that is one line of code. Close as rejected after a single-day spike to confirm the interception mechanism, and invest the saved effort in a Clock abstraction and a CI lint against native time calls.
How can I help you explore Laravel packages today?