rikudou/clock
A lightweight clock abstraction for PHP that makes time-dependent code easier to test. Inject a clock instead of calling time() directly, use the system clock in production, and swap in a fixed or mocked clock in tests to control dates and durations reliably. Framework-agnostic and simple to integra...
Architecture fit. The underlying pattern—injecting a Clock abstraction instead of calling now(), Carbon::now(), or Date::now() directly—is a legitimate, low-coupling design that fits Laravel's container cleanly. It makes time a seam you can control in tests and reason about in domain code (expiry, scheduling, TTL, rate windows). The architectural value here is the interface discipline, not the package: this is a 2–4 class surface (an interface, a system clock, a test double, and a provider) that costs roughly a day to write internally. Assess the pattern, not the artifact.
Integration feasibility. Technically trivial: composer require rikudou/clock, provider registration, one interface binding. No native extensions, no external services, no queue/HTTP surface. The real integration cost sits entirely in the call-site refactor, not the dependency.
Technical risk. High relative to value delivered:
Psr\Clock\ClockInterface, now(): DateTimeImmutable) and Symfony\Component\Clock already solve this with maintenance and a MockClock. If this package predates or diverges from PSR-20, you are adopting a private dialect for a problem the ecosystem has standardized.DateTimeImmutable or mutable DateTime, and whether it normalizes to UTC. Mutable returns reintroduce the exact aliasing bugs the pattern is meant to eliminate.Carbon::setTestNow(), which mutates process-global state and leaks across tests. Explicit DI is safe; a global hijack is not.illuminate/support and PHP floor determine shelf life. With no maintainer activity, a future Laravel/PHP bump strands you on a fork.Key questions to resolve before a decision.
now() return DateTimeImmutable? Is timezone handling explicit (UTC) or inherited from date_default_timezone_set?illuminate/* constraints, and when was the last commit?Stack fit. Suitable for a Laravel 9+ / PHP 8.1+ service codebase where constructor injection is already the norm. It fits poorly as a bolt-on to a legacy codebase that reads wall-clock time in dozens of controllers and models—there the package adds a dependency without changing behavior, and the refactor becomes the whole project.
Alternatives worth weighing first. Given zero dependents, the default recommendation is not to adopt rikudou/clock as a runtime dependency. Ranked options:
symfony/clock — PSR-20 compliant, actively maintained, ships MockClock and ClockSensitiveTrait. Best if we want a supported dependency.SystemClock / FrozenClock — zero third-party risk, full control, MIT-compatible reading of the source for reference.rikudou/clock behind an adapter — only if it demonstrably implements PSR-20 and returns immutable UTC; wrap it so the package type never leaks into domain signatures.Compatibility checks. Confirm auto-discovery via extra.laravel.providers, the illuminate/support version range against our pinned Laravel, and whether the provider registers a singleton (document the shared-state implication). Verify it does not interfere with Carbon::setTestNow() used by existing tests.
Migration path and sequencing.
now(), Carbon::now(), new DateTime, time(), Date::now(); rank by business criticality (billing, expiry, scheduling first).ClockInterface in our own container config; bind SystemClock in production.FrozenClock/MockClock in the test case base class with per-test reset to prevent leakage.Date façade tolerated only at the framework boundary.The sequencing matters more than the choice: the interface and the convention deliver the value, and either path is swappable later if domain code depends only on PSR-20.
Maintenance. Treat this as vendored code. With one star, zero dependents, and no visible security or release process, the expected maintenance burden is "we fork it on the first PHP major." Budget a modest annual cost for dependency review, and prefer an internal implementation that eliminates the fork entirely. MIT licensing makes that copy safe.
Support. No community, no issue-tracker history to mine, no StackOverflow corpus. Onboarding relies on the README plus whatever we write. Mitigate with a short ADR: why the clock seam exists, how to inject it, how to freeze time in tests, and the UTC convention.
Scaling. Runtime cost is negligible—one datetime construction per call. The scaling dimension is organizational: the pattern only pays off if adoption is consistent. A codebase where half the services inject a clock and half call now() is worse than either extreme, because test-time behavior becomes unpredictable. Scaling also implies test-suite growth: a shared frozen clock singleton across a parallel test run is a correctness hazard, so the test double must be per-test, not container-singleton.
Failure modes to design against.
DateTime returns shared by reference, corrupting previously captured timestamps.Carbon::now().Ramp-up. Learning the abstraction is a few hours for any mid-level engineer. The genuine cost is the call-site refactor and the review discipline to keep it from eroding—realistically one to two engineer-weeks spread across a mid-sized service, with ongoing review vigilance.
Verdict. The pattern is right; the package is not a defensible dependency at 1 star and zero dependents. Adopt PSR-20 plus a small internal implementation, or symfony/clock if a supported third-party is preferred, and use this repository at most as a reference implementation behind an adapter.
How can I help you explore Laravel packages today?