g4/cron
g4/cron provides cron scheduling utilities for Laravel and PHP applications, helping you define and manage recurring tasks with cron expressions. A lightweight way to organize scheduled jobs and keep timed workflows predictable.
Architecture fit
g4/cron is a cron-expression parser, not a Laravel package. It ships no service provider, no facade, no config, and no container bindings — it is a library you call from code you already own. That means it does not "integrate" with Laravel so much as compete for the same slot already occupied by dragonmantank/cron-expression, which Laravel pulls in transitively through illuminate/console and which the Scheduler uses to resolve every cron() expression.
Two consequences follow:
g4/cron to a Laravel app means two cron parsers in one process unless you remove or avoid the upstream path entirely. If the fork keeps the upstream namespace, co-installation is a hard conflict; if it renamed the namespace, you get two subtly divergent implementations of the same semantics, which is worse for long-term maintenance than a compile error.everySecond(), everyTwoSeconds(), etc.), implemented by ticking the scheduler loop each second and filtering, not by extending cron syntax. For the mainstream use case, the framework no longer needs a six-field parser.Where the package retains genuine value: parsing user-supplied six-field expressions (admin panels, tenant-configurable schedules, "build your own schedule" UIs), and non-Laravel worker loops or standalone daemons where you control the tick loop. That is a narrow but real niche.
Integration feasibility
Effort is low, confidence in the outcome is low. composer require plus swapping a call site is a one-day change for a competent PHP developer. The blockers are evidentiary, not technical: 6 stars, 0 dependents, and a last release of 2023-11-12 give us no observable evidence of production use, no third-party bug reports to read, and no signal on how the fork tracks upstream. We would be the first serious adopter, which means we would also be the first to find the edge cases.
Technical risk
cron-expression has had correctness fixes (DST handling, DOM/DOW OR-semantics, range/step parsing) over its lifetime. If g4/cron does not rebase, we inherit a snapshot with no patch path.declare(strict_types=1) callers. Deprecation warnings from an unmaintained parser will surface in our logs and erode trust in the scheduler.Key questions
g4/cron a hard fork (renamed namespace) or a drop-in shadowing upstream? Determines whether co-installation is possible at all.composer.json, and is that constraint honest or stale?Stack fit
Poor-to-conditional. Laravel's scheduler is the natural integration point and it is already served. Replacing the parser underneath the Scheduler is high-blast-radius for near-zero benefit — we would be modifying the execution path of every scheduled job in the estate to gain a feature the framework now provides. The defensible integration is beside the Scheduler, not beneath it: use the parser only where we accept arbitrary six-field input from users and need to compute next-run times for display or validation.
Migration path
Treat the parser as an implementation detail behind a port we own:
CronParser (or NextRunCalculator) in our domain with a single method — nextRun(string $expression, DateTimeZone $tz): DateTimeImmutable.dragonmantank/cron-expression for five-field expressions, and only delegate six-field input to g4/cron if we cannot express the requirement otherwise.G4\... classes appear in controllers, models, or job classes. This keeps the swap cost at one file and makes the eventual fork-and-vendor decision a non-event.If the spike shows the package is unsound, the fallback is to vendor the seconds-parsing logic into an internal package under MIT — roughly 200–400 lines of range/step expansion plus a next-run search. That is a known quantity and removes the dependency entirely.
Compatibility
composer.json constraints against our PHP and Laravel versions before anything else; a stale constraint is a fast disqualifier.dragonmantank/cron-expression, which is present in every Laravel app we run.*/n steps is a historical bug class here).Sequencing
L/W/# modifiers) compared field-for-field against dragonmantank/cron-expression for five-field inputs. Any divergence on five-field input is a stop signal.Maintenance
We become the de facto maintainer. With a single upstream release in the window we can observe and no visible rebase discipline, the realistic operating model is: pin the version, never auto-update, and budget a small amount of engineering time per year to re-diff against upstream. If we adopt, we should decide up front whether we are prepared to fork. "Adopt and hope" is the failure mode here.
Support
No vendor, no commercial backing, and 0 dependents means no community of co-sufferers to search when something breaks. Escalation path is: read the source, or fork. That is acceptable for a pure-function parser and unacceptable for anything on the critical path of job execution. This asymmetry should drive the placement decision more than any technical merit.
Scaling
Parsing is CPU-trivial — microseconds per expression, no I/O, no state. It will never be the bottleneck. The scaling risk is indirect and concentrated in the sub-minute feature: second-level scheduling multiplies dispatch volume by 60×, which pushes pressure onto the queue, the cache locks used for withoutOverlapping(), and the database. If we enable second-granularity schedules, we must cap how many tenants can use them and enforce onOneServer/withoutOverlapping by default. Thundering-herd at second boundaries is a real operational failure mode that the parser does nothing to prevent.
Failure modes
| Failure | Detection | Blast radius |
|---|---|---|
| Silent misparse → wrong next-run time | None at runtime; only via missed/duplicate job observation | Missed SLAs, duplicate side effects (emails, invoices) |
| DST transition miscomputation | Once or twice a year, per timezone | Skipped or doubled jobs on the transition hour |
| Two parsers disagree on the same expression | Inconsistent schedule previews vs. actual execution | User trust erosion; hard-to-reproduce tickets |
| Package abandoned / PHP upgrade breaks it | Composer resolution failure or deprecation noise at deploy | Blocks framework upgrades — the expensive one |
| Malformed expression throws at execution, not at save | Job-level exceptions | Noisy alerts, on-call load |
The first three are the dangerous ones because they are silent. Mitigation is a conformance test suite in our CI that pins expected next-run times for a corpus of expressions, and an assertion that schedule previews come from the same parser the scheduler uses.
Ramp-up
Trivial technically — a mid-level PHP developer is productive in an hour. The real ramp-up cost is conceptual: the team must internalise that six-field expressions put seconds first, that this differs from the five-field convention used everywhere else in the codebase, and that the scheduler's own expressions do not go through this path. That asymmetry needs to be documented in the runbook, or someone will debug a "wrong schedule" ticket for a day.
TPM recommendation: Do not adopt as a framework-level dependency. Laravel 11 already covers the sub-minute execution case natively, which removes most of the opportunity this package was built to address. Scope it to a spike against a specific requirement — six-field parsing of user-supplied input — and adopt only behind a port interface, pinned, with a conformance suite and an explicit fork-or-drop decision at the next dependency review. The low score (0.21) and zero dependents are consistent with what the repository shows: a competent small utility with no evidence of production hardening and no maintenance guarantee.
How can I help you explore Laravel packages today?