Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Native Cron Bundle Laravel Package

mintware-de/native-cron-bundle

Symfony bundle for managing native system cron jobs from your app. Configure recurring console commands, install them into the crontab, and manage scheduled tasks without an external worker daemon.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Symfony bundle (mintware-de/native-cron-bundle), not a Laravel package — there is no service provider or Kernel::schedule() integration. In a Laravel codebase you would only realistically port the idea (job classes + system crontab entries); Laravel's own scheduler already does the same thing better. Pick this up when you have a Symfony app (or a mixed repo with one Symfony service) that wants cron jobs defined in PHP rather than in crontab -e.

Minimal setup:

composer require mintware-de/native-cron-bundle

Register Mintware\NativeCronBundle\NativeCronBundle in config/bundles.php, then point the bundle at the directory holding your job classes (typically src/Cron or src/ScheduledTask). Look first at:

  1. config/bundles.php — registration, nothing works without it.
  2. The bundle's config block — this is where the job directory list lives; an empty list is the case v1.0.1 addresses.
  3. The Job/CronJobInterface contract — getInterval() (cron expression) and execute(). Implement that and you have a job.

First use case: take one existing "run this PHP script every 15 minutes" chore, wrap it in a class implementing the interface returning */15 * * * *, then run the bundle's install command (native-cron:install). Verify with native-cron:list and with crontab -l — the first reads the bundle's view, the second reads the truth. Run it once by hand via the bundle's run command (native-cron:run "<FQCN>") before trusting the crontab entry; that separates "my job is broken" from "cron isn't calling it".

Implementation Patterns

One class per job, container-managed. Jobs are resolved through the container, so constructor injection of a logger, a mailer, or a repository works normally. Keep the constructor cheap — it runs on every cron tick, including ticks where the job does nothing interesting.

Treat execute() as a script, not a controller. No request, no session, no output anyone reads. Return early and loudly (log) on precondition failures rather than throwing into the void.

Keep the interval in one place. getInterval() is the single source of truth; the installer writes it into the crontab line. Never hand-edit the generated crontab line — the next install will overwrite it, and you'll spend an hour wondering why your edit vanished.

Deploy pipeline pattern. Run uninstall-then-install as a deploy step, per environment, as the same OS user that cron will run as. In dev/test environments, skip install entirely and invoke jobs manually or from a test — you don't want a laptop's crontab pointing at a staging database.

Overlap protection in the job, not in cron. Cron will happily start a second copy of a 20-minute job scheduled every 10 minutes. A flock on a lock file at the top of execute() is the cheapest fix and survives the bundle being swapped out later.

Testing. execute() is just a method — instantiate the job with mocks and call it. Assert getInterval() returns a valid 5-field expression in a data-provider test if the schedule is business-critical.

Observability. Inject LoggerInterface and log start/finish/duration with the job class name. Cron output is usually mailed to a local mailbox nobody reads, so logs are your only feedback channel.

Gotchas and Tips

v1.0.1's NoopFileLocator is a silencer, not a fix. The change makes the bundle install cleanly when no job locator/directory is configured, instead of erroring at container build time. That's the right call for fresh installs, but it means a misconfigured directory list now looks like "the bundle works, there are simply no jobs." If native-cron:list is empty after upgrading, check the job directory config before assuming your jobs vanished.

Orphaned crontab entries are the classic failure. Install and uninstall both enumerate jobs through the locator. Move a class, rename a namespace, or change the configured directory, and the old crontab line stays behind while a new one is added — you get duplicates or calls to a class that no longer exists. After any refactor that touches job class names or locations, run uninstall before deploying the change, then install. Periodically diff crontab -l against native-cron:list.

Cron's environment is not your shell's. Minimal PATH, no .env exports, different working directory, different timezone. Use absolute paths for the PHP binary, make sure the generated line changes into the project root, and remember that a 09:00 cron expression means 09:00 in the server's timezone, not PHP's configured one.

Discovery is file-based. Job classes must be autoloadable and sit in the scanned directory — a job defined in a vendor package or generated at runtime won't be found. And because the locator reflects on files, clearing the Symfony cache is often required after adding a job class before install will see it.

Per-user crontabs. Running install as deploy while the previous install ran as www-data gives you two independent crontabs, both running the jobs. Standardise on one user and document it.

Exit codes matter more than you think. A job that fails silently every five minutes is worse than one that crashes. Catch exceptions, log with context, and rethrow or exit(1) so monitoring on the cron mailer / exit status can catch it.

Extension point. If you need custom discovery logic (attributes, YAML manifests, database-driven schedules), implement the bundle's locator interface and alias it in the container rather than fighting the default file scanner — that's exactly the seam v1.0.1 added the Noop implementation for.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings