Back to overview

Developing a job scheduler

Developer Tutorials Published on 15.02.2026

Task Scheduler Tutorial

Learn how to automate recurring tasks in Projekt X using a database-driven scheduler.

The Concept

Instead of managing multiple cron jobs in your hosting panel, we will set up a single "Master Cron" that runs every minute. This master script checks a database table in Projekt X to decide which specific tasks (PHP scripts) need to be executed based on their defined intervals.

Step 1: Create the Management Table

First, we need a place to manage our jobs. We will use the "Custom Tables" feature of Projekt X.

  1. Go to Admin > Custom Tables and create a new table.
  2. Name: Cron Jobs
    Technical Name: cron_jobs
  3. Add the following fields to the table:
    Field Name Type Description
    job_name Text A descriptive name for the task.
    script_file Text The filename of the PHP script (e.g., backup.php).
    interval_minutes Number How often should it run? (e.g., 60 for hourly).
    last_run DateTime Stores when the job ran last.
    is_active Checkbox To enable or disable the job.
Tip: Create a folder named jobs in your project root directory. This is where you will place your PHP script files (e.g., jobs/backup.php).
Step 2: The Scheduler Script

Create a file named scheduler.php in your project's root directory. This script will be the engine of your automation.

<?php
// scheduler.php

// 1. Initialize the application environment
// This loads config, database connection, and helper functions
require_once 'init.php';

// 2. Security Check
// Only allow execution from Command Line (CLI) or via a secret token in URL
$secret_token = 'YOUR_SECRET_KEY_HERE'; // Change this!
$is_cli = (php_sapi_name() === 'cli');
$token_match = (isset($_GET['token']) && $_GET['token'] === $secret_token);

if (!$is_cli && !$token_match) {
    http_response_code(403);
    die('Access Denied');
}

echo "Scheduler started at " . date('Y-m-d H:i:s') . "\n";

// 3. Find the physical table name for 'cron_jobs'
// We look up the table definition by its technical name
$table_def = DBGet('custom_tables', null, ['id', 'team'], "technical_name = ?", ['cron_jobs'], '', 1);

if (!$table_def) {
    die("Error: Table 'cron_jobs' not found.\n");
}

$physical_table = "data_team_" . $table_def['team'] . "_" . $table_def['id'];

// 4. Fetch active jobs
// We select jobs that are active
$jobs = DBGet($physical_table, null, ['*'], "is_active = 1");

if (!$jobs) {
    echo "No active jobs found.\n";
    exit;
}

foreach ($jobs as $job) {
    $interval = (int)$job['interval_minutes'];
    $last_run = $job['last_run'] ? strtotime($job['last_run']) : 0;
    $now = time();
    
    // Check if it is time to run
    // (Current time - Last run time) >= (Interval in seconds)
    if (($now - $last_run) >= ($interval * 60)) {
        
        $script_path = __DIR__ . '/jobs/' . basename($job['script_file']);
        
        if (file_exists($script_path)) {
            echo "Running job: " . $job['job_name'] . "...\n";
            
            // Execute the job
            try {
                // Include the script to run it in the current context
                // Alternatively, use exec() for a separate process
                include $script_path;
                
                // Update last_run timestamp
                DBUpdate($physical_table, ['last_run'], [date('Y-m-d H:i:s')], $job['id']);
                
                echo "Done.\n";
            } catch (Exception $e) {
                echo "Error running job: " . $e->getMessage() . "\n";
            }
        } else {
            echo "Error: Script file not found for " . $job['job_name'] . "\n";
        }
        
    } else {
        // Job is not due yet
        // echo "Skipping " . $job['job_name'] . " (not due)\n";
    }
}

echo "Scheduler finished.\n";
?>
Step 3: Setup Cronjob (Plesk/cPanel)

Finally, you need to tell your server to execute the scheduler.php file every minute. This ensures that your jobs run exactly when scheduled.

Option A: Via PHP Command (Recommended)

This runs the script directly on the server. It is faster and doesn't have timeout limits like HTTP.


Command:

/usr/bin/php /var/www/vhosts/yourdomain.com/httpdocs/scheduler.php

Schedule: * * * * * (Every Minute)

Option B: Via URL (HTTP)

Use this if you cannot use the PHP command directly. Don't forget the security token!


Command (wget):

wget -q -O - https://yourdomain.com/scheduler.php?token=YOUR_SECRET_KEY_HERE

Schedule: * * * * * (Every Minute)

How to add it in Plesk:
  1. Log in to your Plesk Panel.
  2. Go to Tools & Settings > Scheduled Tasks (Cronjobs).
  3. Click Add Task.
  4. Task type: Run a PHP script (or "Run a command").
  5. Script path: Select your scheduler.php file.
  6. Run: Select Cron style and enter * * * * *.
  7. Click OK.