www.hubleto.eu Reddit User Guide Stack Overflow LinkedIn Report an issue

Scheduled jobs (crons)

A cron is a PHP class that Hubleto runs periodically: sending queued e-mails, warning about expiring price lists, synchronizing a calendar. Crons are triggered by one system cron job that runs cron.php every minute.

1. Run the cron runner from the system

* * * * * cd /path/to/your/project && php cron.php

cron.php starts the CronManager, which runs every registered cron whose schedule matches the current minute. You can run a single cron at any time, ignoring its schedule, by passing its class name (as it was registered) as the first argument, e.g. php cron.php 'Hubleto\App\Community\Mail\Crons\SendMails'.

erp-project: cron.php
<?php

// bootstrap
require_once(__DIR__ . "/boot.php");

// run cron
$main->cronManager()->init();
$main->cronManager()->run();

NOTE In the project skeleton at the time of writing, cron.php calls $main->cronManager(), but boot.php creates the loader as $hubleto. Until this is fixed, replace $main with $hubleto in your cron.php. Look at the log in log/ when the crons do not run.

2. Write a cron

A cron extends Hubleto\Erp\Cron, defines $schedulingPattern and implements run():

src/Cron.php
<?php declare(strict_types=1);

namespace Hubleto\Erp;

class Cron extends \Hubleto\Erp\Core
{
  // CRON-formatted string specifying the scheduling pattern
  public string $schedulingPattern = '*/5 * * * *';

  public function run(): void
  {
    // to be overriden
  }

}

The default pattern of Hubleto\Erp\Cron is */5 * * * * (every 5 minutes). The $schedulingPattern has five fields: minute hour day-of-month month day-of-week. Each field can be:

Value Meaning
* every value
*/5 every 5th value (*/5 * * * * = every 5 minutes)
7 exactly this value

Supported syntax.

Lists (1,15) and ranges (1-5) are not supported. The day of the week starts with 0 = Monday. The cron is checked once per minute, so the pattern * * * * * runs it every minute.

A cron of an app
apps/PriceLists/Crons/WarnAboutExpiry.php
<?php

namespace Hubleto\App\Community\PriceLists\Crons;

use Hubleto\App\Community\Notifications\Sender;
use Hubleto\App\Community\PriceLists\Models\PriceList;
use Hubleto\App\Community\PriceLists\Services\Counter;

/**
 * Notifies owners of price lists that are about to expire (within the setting expiryWarningDays).
 * Notifications are sent with Notifications\Sender.
 */
class WarnAboutExpiry extends \Hubleto\Erp\Cron
{
  public string $schedulingPattern = '0 7 * * *';

  public function run(): void
  {
    /** @var Counter $counter */
    $counter = $this->getService(Counter::class);
    /** @var Sender $sender */
    $sender = $this->getService(Sender::class);

    foreach ($counter->expiringPriceLists() as $priceList) {
      $idOwner = (int) ($priceList['id_owner'] ?? 0);
      if ($idOwner <= 0) continue;

      $sender->send(
        900,
        ['price-lists', 'expiry'],
        PriceList::class,
        (int) $priceList['id'],
        $idOwner,
        $this->translate('Price list is about to expire'),
        $priceList['code'] . ' ' . $priceList['name'] . ' - ' . $this->translate('valid to') . ' ' . $priceList['valid_to'],
        'price-lists/' . $priceList['id']
      );
    }
  }
}

3. Register the cron

Register it in init() of the Loader of the app:

apps/PriceLists/Loader.php (excerpt)
    $this->cronManager()->addCron(Crons\ActivateAndExpire::class);
    $this->cronManager()->addCron(Crons\WarnAboutExpiry::class);
  }

  /**
   * Installs the app: creates tables (round 1) and seeds default data (round 2).
   *
   * @param int $round
   *
   * @return void
   *
   */
  public function installApp(int $round): void
  {
    if ($round == 1) {
      $modelClasses = [
        Models\PriceList::class, Models\Item::class,
        Models\Assignment::class, Models\Rule::class, Models\History::class, Models\Resolution::class,
        Models\PriceListHasDocument::class,
      ];
      foreach ($modelClasses as $modelClass) {
        /** @var \Hubleto\Erp\Model $model */
        $model = $this->getModel($modelClass);
        $model->upgradeSchema();
      }
    }

addCron() accepts only classes that extend Hubleto\Erp\Cron. The cron is created with getService(), so it is a singleton.

Crons of a project

Crons that do not belong to an app go to src/crons of the project. The CronManager scans the folder and registers every class in the namespace HubletoProject\Cron:

erp-project: src/crons/Example.php
<?php

/*
  This cron does not do anything. It is just an example of how the
  cron should be implemented.
*/

namespace HubletoProject\Cron;

class Example extends \Hubleto\Erp\Cron
{

  // CRON-formatted string specifying the scheduling pattern
  public string $schedulingPattern = '0 0 * * *';

  public function run(): void
  {
    $this->logger()->info("Sample cron started.");
  }

}

Writing a good cron

Related pages