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

Cron Bundle Laravel Package

ite/cron-bundle

ite/cron-bundle is a PHP package for defining, scheduling, and managing recurring cron jobs. It lets you configure scheduled tasks and run them reliably without manual crontab edits, simplifying background job automation.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're adopting first. ite/cron-bundle is a Symfony2-era bundle with a single star and no dependents. Treat it as a small, readable piece of glue code rather than a maintained platform dependency — budget an hour to read the source before wiring it in, and assume you may end up vendoring or forking it.

  1. Install and register. With Composer (or the legacy deps file if you're truly on Symfony 2.0/2.1):

    composer require ite/cron-bundle
    

    Then enable it in app/AppKernel.php:

    new Ite\CronBundle\IteCronBundle(),
    

    Check composer.json for the PHP and Symfony version constraints — a bundle this old will often cap at symfony/symfony: ~2.x and an old PHP minor, which is the single biggest blocker to actually using it.

  2. Look here first, in this order.

    • README.md — likely the only documentation; expect a config sample and one console command example.
    • DependencyInjection/Configuration.php — the authoritative list of config keys. This is where you learn the real schema, not the README.
    • Resources/config/services.xml (or .yml) — the service IDs and tags you'll reference in your own config.
    • Command/ — the runner command you'll invoke from the system crontab.
    • Cron/, Parser/, Schedule/ — the expression parsing and job execution logic.
  3. First use case: schedule one existing console command. The intended workflow is almost certainly: declare jobs in config.yml under an ite_cron: (or similarly named) key, each with a cron expression and a target, then add a single system crontab entry like:

    * * * * * cd /path/to/app && php app/console ite:cron:run --env=prod >> app/logs/cron.log 2>&1
    

    The bundle then decides, per minute, which of your configured jobs are due. Verify the exact command name with php app/console list | grep -i cron — don't trust the README here.

Implementation Patterns

Config-driven job declaration. The core pattern for this class of bundle is a YAML map of jobs, each with an expression plus an action. Expect something shaped like:

# app/config/config.yml
ite_cron:
    jobs:
        nightly_cleanup:
            expression: "0 3 * * *"
            command: "app:cleanup --force"
        reindex:
            expression: "*/15 * * * *"
            service: "app.search.indexer"
            method: "reindex"

Confirm the actual keys against Configuration.php; the two common action styles are console command strings (simplest, gives you a real exit code) and service + method calls (faster, no process fork, but you own error handling).

Prefer commands over service calls for anything non-trivial. Wrapping work in a Symfony command means you get --env, --verbose, memory limits, and exit codes for free, and you can run the job manually the exact same way cron does. Reserve direct service invocation for tiny, in-process tasks.

Integrate with a real scheduler, don't invent one. Run the bundle's runner once per minute from system cron (or systemd timers) and let it fan out. Do not add one crontab line per job — that defeats the purpose and scatters configuration across two systems.

Layer your own wrapper for operational concerns. Because this bundle likely won't give you locking, retries, or structured logging, put them in a thin decorator around your job services:

class LockingJob
{
    public function __construct(private $inner, private LockFactory $locks, private LoggerInterface $logger) {}

    public function run(): void
    {
        $lock = $this->locks->createLock('cron.' . get_class($this->inner), 900);
        if (!$lock->acquire()) {
            $this->logger->warning('Skipped, still running', ['job' => get_class($this->inner)]);
            return;
        }

        $start = microtime(true);
        try {
            $this->inner->run();
        } finally {
            $this->logger->info('Cron job finished', [
                'job'      => get_class($this->inner),
                'duration' => microtime(true) - $start,
            ]);
            $lock->release();
        }
    }
}

symfony/lock is not available on Symfony 2.x — in that era you'd use a flock() on a file or a SELECT ... FOR UPDATE row. Either way, the pattern is the same: every job must be re-entrant-safe or locked.

Per-environment configuration. Jobs that hit external APIs or send mail should not run in dev. Split config:

# config_dev.yml
ite_cron:
    jobs: ~   # or an explicit empty map, depending on how the extension merges

Verify the extension's merge behavior — a bundle that overwrites rather than merges will force you to duplicate the whole tree.

Make jobs observable from day one. Since the bundle is unmaintained, you want to be able to drop it later without losing history. Log to a dedicated channel, and record start/finish/duration so a replacement implementation reads the same data.

Plan the exit ramp. Keep job logic in your own AppBundle command or service classes, and let the bundle be purely a scheduler that points at them. If you do that, replacing ite/cron-bundle with cron/cron-bundle or a plain crontab of commands is a config change, not a rewrite.

Gotchas and Tips

The package is effectively abandoned. One star, zero dependents, Symfony2 EOL'd in 2019. Before adopting: check the last commit date, whether it installs on your PHP version, and whether any of its code uses APIs removed in PHP 7.2+ (each(), mcrypt, dynamic properties, create_function). If it's unmaintained and untested, vendor it into your repo as an application bundle rather than depending on Packagist — you'll want to patch it, and you won't get upstream fixes anyway.

Cron expression parsing is the highest-risk part. Small cron libraries frequently get these wrong:

  • Day-of-week and day-of-month OR semantics (standard cron: if both are restricted, the job runs when either matches — most naive parsers use AND).
  • Step values from a range vs. from * (5-20/3 vs. */3).
  • Leading zeros, 7 vs 0 for Sunday, and named months/days (JAN, MON).

Write a unit test that asserts a handful of expressions resolve to the expected timestamps, using DateTime fixtures. This is cheap insurance and also documents behavior for the next developer.

Timezones. PHP's default timezone and the server's cron timezone frequently disagree. Pick one — ideally set date.timezone explicitly in php.ini — and make sure the bundle's "is this due?" check uses the same zone as the crontab that invokes it. DST transitions are a classic source of double-runs and skipped runs.

Overlapping executions. If a job takes longer than its interval, the next minute's runner will start it again. Nothing in a bundle this size will stop that for you. Add locking (see above) or a "last run" check.

Silent failures. The runner may swallow exceptions from service-style jobs and still exit 0. If you rely on monitoring that alerts on non-zero exit, you'll never hear about failures. Either wrap in try/catch-and-rethrow, or emit a distinct log line and alert on that.

Memory and long processes. The runner is typically a single PHP process that may execute several jobs in sequence. Anything leaking (Doctrine's entity manager is the usual suspect) compounds. For heavy jobs, prefer the console-command action style so each gets a fresh process; call $em->clear() between batches in service-style jobs.

Debugging a "job didn't run". Diagnose in this order:

  1. Did the system cron fire at all? (grep CRON /var/log/syslog, or check your redirect log.)
  2. Did the bundle's runner start? (Log line at process start.)
  3. Did the expression match the current minute? Print the parsed due-list with a -v/--dry-run flag if one exists — if not, add one, it's ten lines and saves hours.
  4. Did the job execute but throw? (Check for swallowed exceptions.)

Extension points worth knowing. Look for a tagged-service mechanism — many bundles of this era let you tag services with something like ite_cron.job to register jobs without touching YAML. That's usually a cleaner integration than a giant config file, and it composes with DI. Also check for a dispatcher/event hook you can subscribe to for pre/post-run logging without forking.

Configuration key names are not guaranteed. Any sample you find online (including this one) is a guess derived from conventions. DependencyInjection/Configuration.php is the only truth. Read it before writing a single line of YAML, and run php app/console config:dump-reference ite_cron to confirm.

Have a replacement candidate in mind. cron/cron-bundle (actively maintained, Symfony 4+) or a plain crontab where each entry is php bin/console app:job-name are both lower-risk. The second option has zero dependencies and is often the right answer for a handful of jobs — the bundle only earns its place if you have many jobs that change frequently and you want them in version-controlled config.

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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core